关于使用httpclient传递json数据乱码的问题

https://blog.csdn.net/li_yan_fei/article/details/68064275

 

首先由此链接 http://www.cnblogs.com/soundcode/p/6560947.html的文章得到的启发

 

今天用httpclient传输json数据,服务端接受数据 中文乱码,下面分别贴上修改前与修改后的代码以及原因分析

(1)修改前:

client端

 

 
  1. public String sendHttpPost(String httpUrl, String data) {

  2.  
  3. // 创建post请求

  4. HttpPost httpPost = new HttpPost(httpUrl);

  5. StringEntity entity;

  6. try {

  7. entity = new StringEntity(data);

  8. entity.setContentEncoding("UTF-8");

  9. entity.setContentType("application/json");

  10. httpPost.setEntity(entity);

  11. } catch (UnsupportedEncodingException e) {

  12. // TODO Auto-generated catch block

  13. e.printStackTrace();

  14. }

  15.  
  16. return sendHttpPost(httpPost);

  17. }

 

 
  1. private String sendHttpPost(HttpPost httpPost) {

  2.  
  3. CloseableHttpClient httpClient = null;

  4. CloseableHttpResponse response = null;

  5. HttpEntity entity = null;

  6. String responseContent = null;

  7.  
  8. // 创建默认的httpclient实例

  9. httpClient = HttpClients.createDefault();

  10. httpPost.setConfig(requestConfig);

  11. httpPost.setHeader("Accept","aplication/json");

  12. httpPost.addHeader("Content-Type","application/json;charset=UTF-8");

  13. // 执行请求

  14. try {

  15. logger.info("开始同步数据");

  16. response = httpClient.execute(httpPost);

  17. entity = response.getEntity();

  18. responseContent = EntityUtils.toString(entity, "UTF-8");

  19. logger.info("数据同步结果:" + responseContent);

  20. } catch (IOException e) {

  21. logger.error("同步数据出错:" + e.toString());

  22. e.printStackTrace();

  23. } finally {

  24. try {

  25. if (response != null) {

  26. response.close();

  27. }

  28. if (httpClient != null) {

  29. httpClient.close();

  30. }

  31.  
  32. } catch (Exception e2) {

  33. logger.error("流关闭出错:" + e2.toString());

  34. }

  35.  
  36. }

  37. return responseContent;

  38. }

(2)修改后

client端

 

 
  1. public String sendHttpPost(String httpUrl, String data) {

  2.  
  3. // 创建post请求

  4. HttpPost httpPost = new HttpPost(httpUrl);

  5. StringEntity entity;

  6. entity = new StringEntity(data,"UTF-8");

  7. entity.setContentType("application/json");

  8. //entity.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));//用这个跟上面一行那个结果一样,可以查看源码

  9. httpPost.setEntity(entity);

  10.  
  11. return sendHttpPost(httpPost);

  12. }

  13.  
  14. private String sendHttpPost(HttpPost httpPost) {

  15.  
  16. CloseableHttpClient httpClient = null;

  17. CloseableHttpResponse response = null;

  18. HttpEntity entity = null;

  19. String responseContent = null;

  20.  
  21. // 创建默认的httpclient实例

  22. httpClient = HttpClients.createDefault();

  23. httpPost.setConfig(requestConfig);

  24. httpPost.setHeader("Accept","aplication/json");

  25.  
  26. httpPost.addHeader("Content-Type","application/json;charset=UTF-8");

  27. }

 

 

 

服务端 代码

 

 

 
  1. //服务端 代码 通过红色字体的代码接受数据

  2. public Map<String, Object> getRequestPostParams(HttpServletRequest request) throws BusinessException {

  3. try {

  4. //接收数据

  5. StringBuffer sb = new StringBuffer() ;

  6. InputStream is = request.getInputStream();

  7. InputStreamReader isr = new InputStreamReader(is, "utf-8");

  8. BufferedReader br = new BufferedReader(isr);

  9. String s = "" ;

  10. while((s=br.readLine())!=null){

  11.  
  12. sb.append(s) ;

  13. }

  14. String strData = sb.toString();

  15.  
  16. if (null == strData || "".equals(strData)) {

  17. return new HashMap<String, Object>();

  18. }

  19. Map<String, Object> params = this.parseJSON2Map(strData);

  20. return params;

  21.  
  22. } catch(Exception e) {

  23. throw new BusinessException(BusinessException.ERROR_INNER, "参数转换错误!");

  24. }

  25. }


 

下面来解释原因:

看到这里  发现了client端的不同的吧,没错 只有一行代码不一样

 

 

entity = new StringEntity(data,"UTF-8");


就是这行代码,因为构造方法的不同造成的

 

 

 

本来参考了 http://www.cnblogs.com/soundcode/p/6560947.html这个博客的文章把问题解决了,但是我发现 我自己的代码明明也设置额编码 为什么会出现乱码呢,于是我就去看源代码的实现,差异在哪里? 下面贴上源代码

 

 

 
  1. public StringEntity(final String string, final ContentType contentType) throws UnsupportedCharsetException {

  2.  
  3. super();

  4. Args.notNull(string, "Source string");

  5. Charset charset = contentType != null ? contentType.getCharset() : null;

  6. if (charset == null) {

  7. charset = HTTP.DEF_CONTENT_CHARSET;

  8. }

  9. try {

  10. this.content = string.getBytes(charset.name());

  11. } catch (final UnsupportedEncodingException ex) {

  12. // should never happen

  13. throw new UnsupportedCharsetException(charset.name());

  14. }

  15. if (contentType != null) {

  16. setContentType(contentType.toString());

  17. }

  18.  
  19. }


 

然后就发现,在new StringEntity的时候,就已经将数据根据编码进行了处理,也就是说,如果你调用 new StringEntity(String string)此构造方法,就会使用其默认的编码进行转码(ISO-8859-1),无论你后面设置多少次(

 

 

entity.setContentEncoding("UTF-8");

 

或者

 

 

 

httpPost.addHeader("Content-Type","application/json;charset=UTF-8");


 

 

 

都不会改变字符串已经被按转码变成Byte[]数组的事实,当然在请求中设定传输编码格式还是要做的。

其实说这么多 ,解决问题的关键就一句话,在new StringEntity()的时候指定编码就解决了,因为在new的同时已经做了字符串的转码操作

之所以说这么多,是想告诉自己,问题解决了固然是好,但应该知道为什么这么做,多看源码,多问自己为什么,仅此共勉。

 

本人也是刚毕业的小菜鸟一个,有不足之处欢迎补充,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值