commons httpclient - Додавання параметрів рядка запиту до запиту GET / POST


79

Я використовую спільний HttpClient для здійснення http-виклику сервлету Spring. Мені потрібно додати кілька параметрів у рядок запиту. Тому я роблю наступне:

HttpRequestBase request = new HttpGet(url);
HttpParams params = new BasicHttpParams();
params.setParameter("key1", "value1");
params.setParameter("key2", "value2");
params.setParameter("key3", "value3");
request.setParams(params);
HttpClient httpClient = new DefaultHttpClient();
httpClient.execute(request);

Однак, коли я намагаюся прочитати параметр у сервлеті, використовуючи

((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest().getParameter("key");

він повертає null. Насправді параметрMap абсолютно порожній. Коли я вручну додаю параметри до URL-адреси перед створенням запиту HttpGet, параметри доступні в сервлеті. Те саме, коли я вдарив сервлет із браузера за допомогою URL-адреси з доданим queryString.

У чому тут помилка? У httpclient 3.x GetMethod мав метод setQueryString () для додавання рядка запитів. Що еквівалентно в 4.x?

Відповіді:


136

Ось як можна додати параметри рядка запиту за допомогою HttpClient 4.2 і пізніших версій:

URIBuilder builder = new URIBuilder("http://example.com/");
builder.setParameter("parts", "all").setParameter("action", "finish");

HttpPost post = new HttpPost(builder.build());

Отриманий URI буде виглядати так:

http://example.com/?parts=all&action=finish

32

Якщо ви хочете додати параметр запиту після того, як створили запит, спробуйте HttpRequestпередати файл у HttpBaseRequest. Потім ви можете змінити URI литого запиту:

HttpGet someHttpGet = new HttpGet("http://google.de");

URI uri = new URIBuilder(someHttpGet.getURI()).addParameter("q",
        "That was easy!").build();

((HttpRequestBase) someHttpGet).setURI(uri);

12

HttpParamsІнтерфейс не існує для завдання параметрів рядка запиту, то для визначення поведінки в середовищі виконання HttpClientоб'єкта.

Якщо ви хочете передати параметри рядка запиту, вам потрібно зібрати їх за URL-адресою самостійно, наприклад

new HttpGet(url + "key1=" + value1 + ...);

Не забудьте спочатку закодувати значення (використовуючи URLEncoder).


3
Чи немає можливості додати параметр рядка запиту ПІСЛЯ об’єкта запиту вже створений? Якщо ні, чи існує інший стандартний спосіб передачі параметрів сервлету для будь-якого методу запиту (GET / PUT / POST)?
Oceanic

5

Я використовую httpclient 4.4.

Для запиту solr я використав наступний спосіб, і він спрацював.

NameValuePair nv2 = new BasicNameValuePair("fq","(active:true) AND (category:Fruit OR category1:Vegetable)");
nvPairList.add(nv2);
NameValuePair nv3 = new BasicNameValuePair("wt","json");
nvPairList.add(nv3);
NameValuePair nv4 = new BasicNameValuePair("start","0");
nvPairList.add(nv4);
NameValuePair nv5 = new BasicNameValuePair("rows","10");
nvPairList.add(nv5);

HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(url);
URI uri = new URIBuilder(request.getURI()).addParameters(nvPairList).build();
            request.setURI(uri);

HttpResponse response = client.execute(request);    
if (response.getStatusLine().getStatusCode() != 200) {

}

BufferedReader br = new BufferedReader(
                             new InputStreamReader((response.getEntity().getContent())));

String output;
System.out.println("Output  .... ");
String respStr = "";
while ((output = br.readLine()) != null) {
    respStr = respStr + output;
    System.out.println(output);
}

Для цієї відповіді було б корисно отримати додаткові пояснення
Д. Бен Нобле

Ця відповідь була дуже корисною для мого випадку, оскільки я не міг знайти спосіб ініціалізації URIBuilder за допомогою повного URI, наприклад http://myserver/apipath. При ініціалізації з ним URIBuilder лише використовував http://myserverта ігнорував /apipath. URI надавався зовні, тому я не хотів аналізувати його вручну, лише щоб використовувати URIBuilder.
nuoritoveri

2

Цей підхід нормальний, але не спрацює, коли ви отримуєте параметри динамічно, іноді 1, 2, 3 або більше, так само, як пошуковий запит SOLR (наприклад)

Ось більш гнучке рішення. Сирий, але може бути доопрацьований

public static void main(String[] args) {

    String host = "localhost";
    String port = "9093";

    String param = "/10-2014.01?description=cars&verbose=true&hl=true&hl.simple.pre=<b>&hl.simple.post=</b>";
    String[] wholeString = param.split("\\?");
    String theQueryString = wholeString.length > 1 ? wholeString[1] : "";

    String SolrUrl = "http://" + host + ":" + port + "/mypublish-services/carclassifications/" + "loc";

    GetMethod method = new GetMethod(SolrUrl );

    if (theQueryString.equalsIgnoreCase("")) {
        method.setQueryString(new NameValuePair[]{
        });
    } else {
        String[] paramKeyValuesArray = theQueryString.split("&");
        List<String> list = Arrays.asList(paramKeyValuesArray);
        List<NameValuePair> nvPairList = new ArrayList<NameValuePair>();
        for (String s : list) {
            String[] nvPair = s.split("=");
            String theKey = nvPair[0];
            String theValue = nvPair[1];
            NameValuePair nameValuePair = new NameValuePair(theKey, theValue);
            nvPairList.add(nameValuePair);
        }
        NameValuePair[] nvPairArray = new NameValuePair[nvPairList.size()];
        nvPairList.toArray(nvPairArray);
        method.setQueryString(nvPairArray);       // Encoding is taken care of here by setQueryString

    }
}

GetMethod? це з httpclient? тому що питання в цьому.
Вальфрат,

Так, з org.apache.commons.httpclient.methods.
Рахул Сайні

так, але, схоже, це для версії 3.x, у версії 4.x це тепер
org.apache.http.client.methods.HttpGet

0

Ось як я реалізував свій конструктор URL-адрес. Я створив один сервісний клас для надання параметрів для URL-адреси

public interface ParamsProvider {

    String queryProvider(List<BasicNameValuePair> params);

    String bodyProvider(List<BasicNameValuePair> params);
}

Реалізація методів наведена нижче

@Component
public class ParamsProviderImp implements ParamsProvider {
    @Override
    public String queryProvider(List<BasicNameValuePair> params) {
        StringBuilder query = new StringBuilder();
        AtomicBoolean first = new AtomicBoolean(true);
        params.forEach(basicNameValuePair -> {
            if (first.get()) {
                query.append("?");
                query.append(basicNameValuePair.toString());
                first.set(false);
            } else {
                query.append("&");
                query.append(basicNameValuePair.toString());
            }
        });
        return query.toString();
    }

    @Override
    public String bodyProvider(List<BasicNameValuePair> params) {
        StringBuilder body = new StringBuilder();
        AtomicBoolean first = new AtomicBoolean(true);
        params.forEach(basicNameValuePair -> {
            if (first.get()) {
                body.append(basicNameValuePair.toString());
                first.set(false);
            } else {
                body.append("&");
                body.append(basicNameValuePair.toString());
            }
        });
        return body.toString();
    }
}

Коли нам потрібні параметри запиту для нашої URL-адреси, я просто телефоную до служби та створюю її. Приклад цього наведено нижче.

Class Mock{
@Autowired
ParamsProvider paramsProvider;
 String url ="http://www.google.lk";
// For the query params price,type
 List<BasicNameValuePair> queryParameters = new ArrayList<>();
 queryParameters.add(new BasicNameValuePair("price", 100));
 queryParameters.add(new BasicNameValuePair("type", "L"));
url = url+paramsProvider.queryProvider(queryParameters);
// You can use it in similar way to send the body params using the bodyProvider

}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.