HttpClient在传参和返回结果的中文乱码问题

有问题请教:

我将一个file中的json字符串取出,实例化一个StringEntiry,将json字符串写入请求体中。然后无论我以哪种编码方式输出StringEntity中的content,其中的中文均为乱码“???”。 这是怎么回事?

总结:就是在传递的参数中设置,这个很重要

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

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

(1)修改前:

client端

[java]  view plain  copy
  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. }  

[java]  view plain  copy
  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端

[java]  view plain  copy
  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. }  

 

服务端 代码

[java]  view plain  copy
  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端的不同的吧,没错 只有一行代码不一样

[java]  view plain  copy
  1. entity = new StringEntity(data,"UTF-8");  

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

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

[java]  view plain  copy
  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),无论你后面设置多少次(

[java]  view plain  copy
  1. entity.setContentEncoding("UTF-8");  

或者

[java]  view plain  copy
  1. httpPost.addHeader("Content-Type","application/json;charset=UTF-8");  


 

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

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

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



原文:http://blog.csdn.net/li_yan_fei/article/details/68064275


已标记关键词 清除标记
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质? 你是否想成为一名资深开发人员,想开发别人做不了的高性能程序? 你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹?   那么C++就是你个人能力提升,职业之路进阶的不二之选。 【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。 2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。 3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。 【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署; 2.吊打一切关于C++的笔试面试题; 3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。 【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块 基础篇 本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。 进阶篇 本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。 提升篇: 本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页