commons httpclient - Hinzufügen von Abfragezeichenfolgenparametern zur GET / POST-Anforderung


78

Ich verwende Commons HttpClient, um einen http-Aufruf eines Spring-Servlets durchzuführen. Ich muss ein paar Parameter in die Abfragezeichenfolge einfügen. Also mache ich folgendes:

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);

Allerdings, wenn ich versuche, den Parameter im Servlet mit zu lesen

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

es gibt null zurück. Tatsächlich ist die parameterMap vollständig leer. Wenn ich die Parameter vor dem Erstellen der HttpGet-Anforderung manuell an die URL anhänge, sind die Parameter im Servlet verfügbar. Das Gleiche gilt, wenn ich das Servlet vom Browser aus über die URL mit angehängtem queryString aufrufe.

Was ist der Fehler hier? In httpclient 3.x verfügte GetMethod über eine setQueryString () -Methode zum Anhängen des Querystrings. Was ist das Äquivalent in 4.x?

Antworten:


134

So fügen Sie Abfragezeichenfolgenparameter mit HttpClient 4.2 und höher hinzu:

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

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

Die resultierende URI würde folgendermaßen aussehen:

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

32

Wenn Sie nach dem Erstellen der Anforderung einen Abfrageparameter hinzufügen möchten, versuchen Sie, den HttpRequestin a umzuwandeln HttpBaseRequest. Dann können Sie den URI der gegossenen Anforderung ändern:

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

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

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

12

Die HttpParamsSchnittstelle dient nicht zum Angeben von Abfragezeichenfolgenparametern, sondern zum Festlegen des Laufzeitverhaltens des HttpClientObjekts.

Wenn Sie Abfragezeichenfolgenparameter übergeben möchten, müssen Sie diese selbst in der URL zusammenstellen, z

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

Denken Sie daran, die Werte zuerst zu codieren (mit URLEncoder).


3
Gibt es keine Möglichkeit, einen Abfragezeichenfolgenparameter hinzuzufügen, nachdem das Anforderungsobjekt bereits erstellt wurde? Wenn nicht, gibt es eine andere Standardmethode zum Übergeben von Parametern an das Servlet für eine Anforderungsmethode (GET / PUT / POST)?
Oceanic

5

Ich benutze httpclient 4.4.

Für die Solr-Abfrage habe ich den folgenden Weg verwendet und es hat funktioniert.

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);
}

Diese Antwort würde von mehr Erklärung profitieren
D. Ben Knoble

Diese Antwort war für meinen Fall sehr nützlich, da ich keine Möglichkeit gefunden habe, URIBuilder mit einem vollständigen URI-Beispiel zu initialisieren http://myserver/apipath. Bei der Initialisierung wurde URIBuilder nur verwendet http://myserverund ignoriert /apipath. Der URI wurde extern bereitgestellt, daher wollte ich ihn nicht manuell analysieren, nur um URIBuilder zu verwenden.
Nuoritoveri

2

Dieser Ansatz ist in Ordnung, funktioniert jedoch nicht, wenn Sie Parameter dynamisch abrufen, manchmal 1, 2, 3 oder mehr, genau wie bei einer SOLR-Suchabfrage (zum Beispiel).

Hier ist eine flexiblere Lösung. Roh, kann aber verfeinert werden.

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? ist es von httpclient? weil die Frage ist darüber.
Walfrat

Ja, aus org.apache.commons.httpclient.methods.
Rahul Saini

ah ja, aber es scheint, dass es für die 3.x-Version ist, in 4.x ist es jetzt org.apache.http.client.methods.HttpGet
Walfrat

0

So habe ich meinen URL Builder implementiert. Ich habe eine Serviceklasse erstellt, um die Parameter für die URL bereitzustellen

public interface ParamsProvider {

    String queryProvider(List<BasicNameValuePair> params);

    String bodyProvider(List<BasicNameValuePair> params);
}

Die Implementierung der Methoden ist unten

@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();
    }
}

Wenn wir die Abfrageparameter für unsere URL benötigen, rufe ich einfach den Dienst auf und erstelle ihn. Ein Beispiel dafür finden Sie weiter unten.

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

}

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.