昨天用httpclient的HttpPost发送带中文参数的数据去调试第三方接口时候,出现了中文乱码,见下面控制台打印信息的最后一行,city的中文值变成了%3F%3F%3F%3F%3F%3F。
09:29:49.383 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - Executing request POST /xxx/xxx/xxx HTTP/1.1
09:29:49.383 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - Target auth state: UNCHALLENGED
09:29:49.384 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - Proxy auth state: UNCHALLENGED
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> POST /xxx/xxx/xxx HTTP/1.1
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Content-Length: 99
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Content-Type: application/x-www-form-urlencoded
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Host: xxx.xxx.xxx.xxx:8180
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Connection: Keep-Alive
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.3 (Java 1.5 minimum; Java/1.8.0_91)
09:29:49.388 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Accept-Encoding: gzip,deflate
09:29:49.389 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "POST /xxx/xxx/xxx HTTP/1.1[\r][\n]"
09:29:49.389 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Content-Length: 99[\r][\n]"
09:29:49.389 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Content-Type: application/x-www-form-urlencoded[\r][\n]"
09:29:49.389 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Host: xxx.xxx.xxx.xxx:8180[\r][\n]"
09:29:49.389 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
09:29:49.391 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.3 (Java 1.5 minimum; Java/1.8.0_91)[\r][\n]"
09:29:49.391 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
09:29:49.391 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "[\r][\n]"
09:29:49.392 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "key=xxx&city=%3F%3F%3F%3F%3F%3F&agt=xxxx&depart=yyy"
下面是请求代码
public String executePost(String url, Map<String, String> param) throws HttpException, IOException {
String result = null;
List<NameValuePair> nvps = HttpUtil.buildNameValuePair(param);
CloseableHttpClient httpclient = HttpClients.createDefault();
EntityBuilder builder = EntityBuilder.create();
try {
HttpPost httpPost = new HttpPost(url);
builder.setParameters(nvps);
httpPost.setEntity(builder.build());
CloseableHttpResponse response = httpclient.execute(httpPost);
try {
HttpEntity entity = response.getEntity();
if (response.getStatusLine().getReasonPhrase().equals("OK") && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
result = EntityUtils.toString(entity, "UTF-8");
}
EntityUtils.consume(entity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
return result;
}
public static void main(String[] args) {
HttpUtil helper = new HttpUtil();
Map<String, String> param = new HashMap<>();
param.put("key", "xxx");
param.put("agt", "xxx");
param.put("depart", "yyy");
param.put("city", "浙江省杭州市");
String url = "http://xxx.xxx.xxx.xxx:8180/xxx/xxx/xxx";
try {
String ret = helper.executePost(url, param);
System.out.println(ret);
} catch (HttpException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
后来去百度找到了一种可行的解决方式,下面贴上修改后的请求代码
/**
*
* @author 北北
* @date 2017年11月9日上午9:53:23
* @param url 请求路径
* @param param 请求参数
* @param charset 编码方式
* @return
* @throws HttpException
* @throws IOException
*/
public String executePost(String url, Map<String, String> param, String charset) throws HttpException, IOException {
String result = null;
List<NameValuePair> nvps = HttpUtil.buildNameValuePair(param);
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpPost httpPost = new HttpPost(url);
UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(nvps, charset);
httpPost.setEntity(uefEntity);
CloseableHttpResponse response = httpclient.execute(httpPost);
try {
HttpEntity entity = response.getEntity();
if (response.getStatusLine().getReasonPhrase().equals("OK") && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
result = EntityUtils.toString(entity, "UTF-8");
}
EntityUtils.consume(entity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
return result;
}
public static void main(String[] args) {
HttpUtil helper = new HttpUtil();
Map<String, String> param = new HashMap<>();
param.put("key", "xxx");
param.put("agt", "xxx");
param.put("depart", "yyy");
param.put("city", "浙江省杭州市");
String url = "http://xxx.xxx.xxx.xxx:8180/xxx/xxx/xxx";
try {
String ret = helper.executePost(url, param);
System.out.println(ret);
} catch (HttpException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
这里主要是将设置参数的类由EntityBuilder换成了UrlEncodedFormEntity,从名称上可以看出后者是对表单数据路径编码的。
参考文章: HttpClient使用详解
网友评论