HttpClient 请求参数中文编码问题
来源:互联网 发布:手机乐器软件架子鼓 编辑:程序博客网 时间:2024/06/02 02:17
- 目录
- 问题
- 问题分析
问题
首先看下我们正常使用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(); }}
阅读全文