您的位置:首页 > 理论基础 > 计算机网络

HttpClient 请求参数中文编码问题

2017-12-25 15:56 591 查看
目录

问题

问题分析

问题

首先看下我们正常使用HttpClient作POST请求的处理方法

public static String doHttpPost(String url, JSONObject params)
throws IOException {
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpPost httpPost = new HttpPost(url);

List<NameValuePair> nvps = new ArrayList<NameValuePair>();
params.forEach((key, value) -> {
if (value != null) {
nvps.add(new BasicNameValuePair(key, String.valueOf(value)));
} else {
nvps.add(new BasicNameValuePair(key, ""));
}
});

HttpEntity reqEntity = EntityBuilder
.create()
.setContentEncoding('UTF-8")
.setParameters(nvps).build();
httpPost.setEntity(reqEntity);
CloseableHttpResponse response = httpclient.execute(httpPost);
HttpEntity entity = response.getEntity();
String result = null;
if (entity != null) {
result = EntityUtils.toString(entity, "UTF-8");
}
EntityUtils.consume(entity);
response.close();
return result;
} finally {
httpclient.close();
}
}


初看之下没有问题,平时使用也经常看不出问题(因为程序员在作请求都会本能规避请求参数中含有中文内容),但是一旦传参
params
含有中文,就会在收到的请求中看到
???
这种分分钟让程序猿高潮的东西!因为
setContentEncoding('UTF-8")
这一句根本没起作用

问题分析

请求参数的处理主要集中在下面这部分

HttpEntity reqEntity = EntityBuilder.create().setContentEncoding('UTF-8").setParameters(nvps).build();


可以看出是典型的
装饰者模式
,通过Maven查看
EntityBuilder
源码中的
build()
函数如下:

public HttpEntity build() {
final AbstractHttpEntity e;
//... 略 ...
else if (this.parameters != null) {
e = new UrlEncodedFormEntity(this.parameters,
this.contentType != null ? this.contentType.getCharset() : null);
}
//... 略 ...
e.setContentEncoding(this.contentEncoding);
//... 略 ...
return e;
}


可以看到,这个
setContentEncoding
不是设置请求参数编码的,参数编码设置是
e = new UrlEncodedFormEntity(this.parameters,this.contentType != null ? this.contentType.getCharset() : null);
这一句完成的,所以参数编码要用
setContentType()
来设置。再来看
ContentType
的源码

public static final ContentType APPLICATION_ATOM_XML = create(
"application/atom+xml", Consts.ISO_8859_1);
public static final ContentType APPLICATION_FORM_URLENCODED = create(
"application/x-www-form-urlencoded", Consts.ISO_8859_1);
public static final ContentType APPLICATION_JSON = create(
"application/json", Consts.UTF_8);
public static final ContentType APPLICATION_OCTET_STREAM = create(
"application/octet-stream", (Charset) null);
public static final ContentType APPLICATION_SVG_XML = create(
"application/svg+xml", Consts.ISO_8859_1);
public static final ContentType APPLICATION_XHTML_XML = create(
"application/xhtml+xml", Consts.ISO_8859_1);
public static final ContentType APPLICATION_XML = create(
"application/xml", Consts.ISO_8859_1);
public static final ContentType MULTIPART_FORM_DATA = create(
"multipart/form-data", Consts.ISO_8859_1);
public static final ContentType TEXT_HTML = create(
"text/html", Consts.ISO_8859_1);
public static final ContentType TEXT_PLAIN = create(
"text/plain", Consts.ISO_8859_1);
public static final ContentType TEXT_XML = create(
"text/xml", Consts.ISO_8859_1);
public static final ContentType WILDCARD = create(
"*/*", (Charset) null);


尼玛,固有的全是ISO_8859_1,要中文啊,还好有
ContentType.create(mimeType, charset)
可以用,所以最终完成的代码如下:

public static String doHttpPost(String url, JSONObject params)
throws IOException {
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpPost httpPost = new HttpPost(url);

List<NameValuePair> nvps = new ArrayList<NameValuePair>();
params.forEach((key, value) -> {
if (value != null) {
nvps.add(new BasicNameValuePair(key, String.valueOf(value)));
} else {
nvps.add(new BasicNameValuePair(key, ""));
}
});

HttpEntity reqEntity = EntityBuilder
.create()
.setContentType(
ContentType.create(
"application/x-www-form-urlencoded",
Consts.UTF_8)).setParameters(nvps).build();
httpPost.setEntity(reqEntity);
CloseableHttpResponse response = httpclient.execute(httpPost);
HttpEntity entity = response.getEntity();
String result = null;
if (entity != null) {
result = EntityUtils.toString(entity, "UTF-8");
}
EntityUtils.consume(entity);
response.close();
return result;
} finally {
httpclient.close();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HttpClient 中文乱码