Commons httpclient-向 GET/POST 请求添加查询字符串参数

我使用 commons HttpClient 对 Springservlet 进行 http 调用。我需要在查询字符串中添加一些参数。所以我这样做:

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

但是,当我尝试读取 servlet 中的参数时,使用

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

返回 null。实际上参数 Map 是完全空的。当我在创建 HttpGet 请求之前手动将参数附加到 URL 时,这些参数在 servlet 中是可用的。当我从浏览器中使用附加了 queryString 的 URL 命中 servlet 时也是如此。

这里出了什么问题?在 httpclient 3.x 中,GetMethod 有一个 setQueryString ()方法来追加 querystring。4.x 的等价物是什么?

185921 次浏览

The HttpParams interface isn't there for specifying query string parameters, it's for specifying runtime behaviour of the HttpClient object.

If you want to pass query string parameters, you need to assemble them on the URL yourself, e.g.

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

Remember to encode the values first (using URLEncoder).

If you want to add a query parameter after you have created the request, try casting the HttpRequest to a HttpBaseRequest. Then you can change the URI of the casted request:

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


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


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

Here is how you would add query string parameters using HttpClient 4.2 and later:

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


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

The resulting URI would look like:

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

This approach is ok but will not work for when you get params dynamically , sometimes 1, 2, 3 or more, just like a SOLR search query (for example)

Here is a more flexible solution. Crude but can be refined.

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


}
}

I am using httpclient 4.4.

For solr query I used the following way and it worked.

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

This is how I implemented my URL builder. I have created one Service class to provide the params for the URL

public interface ParamsProvider {


String queryProvider(List<BasicNameValuePair> params);


String bodyProvider(List<BasicNameValuePair> params);
}


The Implementation of methods are below

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


When we need the query params for our URL, I simply call the service and build it. Example for that is below.

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


}


Im using Java 8 and apache httpclient 4.5.13

HashMap<String, String> customParams = new HashMap<>();
customParams.put("param1", "ABC");
customParams.put("param2", "123");


URIBuilder uriBuilder = new URIBuilder(baseURL);


for (String paramKey : customParams.keySet()) {
uriBuilder.addParameter(paramKey, customParams.get(paramKey));
}


System.out.println(uriBuilder.build().toASCIIString()); // ENCODED URL
System.out.println(uriBuilder.build().toString); // NORMAL URL

Full example with DTO

public class HttpResponseDTO {
private Integer statusCode;
private String body;
private String errorMessage;
    

public Integer getStatusCode() {
return statusCode;
}
public void setStatusCode(Integer statusCode) {
this.statusCode = statusCode;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
    /**
*
* @param destinationURL
* @param params
* @param headers
* @return HttpResponseDTO
*/
public static HttpResponseDTO get(String baseURL, Boolean encodeURL, HashMap<String, String> params, HashMap<String, String> headers) {


final HttpResponseDTO httpResponseDTO = new HttpResponseDTO();


// ADD PARAMS IF
if (params != null && Boolean.FALSE.equals(params.isEmpty())) {
URIBuilder uriBuilder;
try {
uriBuilder = new URIBuilder(baseURL);


for (String paramKey : params.keySet()) {
uriBuilder.addParameter(paramKey, params.get(paramKey));
}


// CODIFICAR URL ?
if (Boolean.TRUE.equals(encodeURL)) {
baseURL = uriBuilder.build().toASCIIString();
} else {
baseURL = uriBuilder.build().toString();
}
} catch (URISyntaxException e) {
httpResponseDTO.setStatusCode(500);
httpResponseDTO.setErrorMessage("ERROR AL CODIFICAR URL: " + e.getMessage());
return httpResponseDTO;
}
}




// HACER PETICION HTTP
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
final HttpGet get = new HttpGet(baseURL);


// ADD HEADERS
if (headers != null && Boolean.FALSE.equals(headers.isEmpty())) {
for (String headerKey : headers.keySet()) {
get.setHeader(headerKey, headers.get(headerKey));
}
}


try (CloseableHttpResponse response = httpClient.execute(get);) {
HttpEntity httpEntity = response.getEntity();
if (httpEntity != null) {
httpResponseDTO.setBody(EntityUtils.toString(httpEntity));
httpResponseDTO.setStatusCode(response.getStatusLine().getStatusCode());
}
} catch(Exception e) {
httpResponseDTO.setStatusCode(500);
httpResponseDTO.setErrorMessage(e.getMessage());
return httpResponseDTO;
}
} catch(Exception e) {
httpResponseDTO.setStatusCode(500);
httpResponseDTO.setErrorMessage(e.getMessage());
return httpResponseDTO;
}


return httpResponseDTO;
}