Java commons httpclient-向GET/POST请求添加查询字符串参数
我正在使用commons HttpClient对Spring servlet进行http调用。我需要在查询字符串中添加一些参数。因此,我做了以下工作:Java commons httpclient-向GET/POST请求添加查询字符串参数,java,apache-httpclient-4.x,Java,Apache Httpclient 4.x,我正在使用commons HttpClient对Spring servlet进行http调用。我需要在查询字符串中添加一些参数。因此,我做了以下工作: HttpRequestBase request = new HttpGet(url); HttpParams params = new BasicHttpParams(); params.setParameter("key1", "value1"); params.setParameter("key2", "value2"); params.se
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。事实上,parameterMap是完全空的。当我在创建HttpGet请求之前手动将参数附加到url时,这些参数在servlet中可用。当我使用附加了queryString的URL从浏览器中点击servlet时也是如此
这里的错误是什么?在httpclient 3.x中,GetMethod有一个setQueryString()方法来附加querystring。4.x中的等价物是什么?该
HttpParams
接口不用于指定查询字符串参数,而是用于指定HttpClient
对象的运行时行为
如果您想传递查询字符串参数,您需要自己在URL上组装它们,例如
new HttpGet(url + "key1=" + value1 + ...);
请记住首先对值进行编码(使用
URLEncoder
)。如果要在创建请求后添加查询参数,请尝试将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);
以下是如何使用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
这种方法可以,但在动态获取参数(有时是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
}
}
publicstaticvoidmain(字符串[]args){
String host=“localhost”;
字符串端口=“9093”;
String param=“/10-2014.01?description=cars&verbose=true&hl=true&hl.simple.pre=&hl.simple.post=”;
字符串[]批发字符串=参数拆分(“\\?”);
字符串theQueryString=whistString.length>1?whistString[1]:“”;
String SolrUrl=“http://“+host+”:“+port+”/mypublish services/carclassifications/”+“loc”;
GetMethod=新的GetMethod(SolrUrl);
if(queryString.equalsIgnoreCase(“”){
方法.setQueryString(新的NameValuePair[]{
});
}否则{
String[]paramKeyValuesArray=querystring.split(“&”);
List List=Arrays.asList(paramKeyValuesArray);
List nvPairList=newarraylist();
用于(字符串s:列表){
字符串[]nvPair=s.split(“”);
字符串theKey=nvPair[0];
字符串theValue=nvPair[1];
NameValuePair NameValuePair=新的NameValuePair(键,值);
添加(nameValuePair);
}
NameValuePair[]nvPairArray=新的NameValuePair[nvPairList.size()];
nvPairList.toArray(nvpairray);
method.setQueryString(nvPairArray);//这里由setQueryString负责编码
}
}
我正在使用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);
}
这就是我实现URL生成器的方式。 我创建了一个服务类来为URL提供参数
public interface ParamsProvider {
String queryProvider(List<BasicNameValuePair> params);
String bodyProvider(List<BasicNameValuePair> params);
}
公共接口参数提供程序{
字符串查询提供程序(列表参数);
字符串bodyProvider(列表参数);
}
方法的实现如下所示
@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();
}
}
@组件
公共类ParamsProviderImp实现ParamsProvider{
@凌驾
公共字符串查询提供程序(列表参数){
StringBuilder查询=新建StringBuilder();
AtomicBoolean first=新的AtomicBoolean(真);
参数forEach(basicNameValuePair->{
if(first.get()){
查询。追加(“?”);
append(basicNameValuePair.toString());
首先,设置(false);
}否则{
查询。追加(“&”);
append(basicNameValuePair.toString());
}
});
返回query.toString();
}
@凌驾
公共字符串bodyProvider(列表参数){
StringBuilder主体=新的StringBuilder();
AtomicBoolean first=新的AtomicBoolean(真);
参数forEach(basicNameValuePair->{
if(first.get()){
body.append(basicNameValuePair.toString());
首先,设置(false);
}否则{
正文.附加(“&”);
body.append(basicNameValuePair.toString());
}
});
返回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
}
类模拟{
@自动连线
ParamsProvider ParamsProvider;
字符串url=”http://www.google.lk";
//对于查询参数price,键入
List queryParameters=new ArrayList();
添加(新的BasicNameValuePair(“价格”,100));
添加(新的BasicNameValuePair(“类型”,“L”);
url=url+paramsProvider.queryProvider(queryParameters);
//您可以以类似的方式使用bodyProvider发送body参数
}
创建请求对象后,是否无法添加查询字符串参数?如果没有,是否有其他标准方法为任何请求方法(GET/PUT/POST)将参数传递到servlet?此答案将受益于更多解释此答案对我的案例非常有用,因为我找不到使用完整URI初始化URIBuilder的方法,例如http://myserver/apipath
。使用它初始化时,URIBuilder仅使用http://myserver
并忽略/apipath
。URI是外部提供的,所以我不想为了使用URIBuilder.GetMethod而手动解析它?它是来自httpclient的吗?因为问题是关于它的。是的,来自org.apache.commons.httpclient.methods.ah是的,但它似乎适用于3.x版本,在4.x中,它现在是org.apache.http.client.methods.HttpGet