解决使用httpclient传递json数据乱码的问题
今天用httpclient传输json数据,服务端接受数据 中文乱码,下面分别贴上修改前与修改后的代码以及原因分析
(1)修改前:
client端
public string sendhttppost(string httpurl, string data) { // 创建post请求 httppost httppost = new httppost(httpurl); stringentity entity; try { entity = new stringentity(data); entity.setcontentencoding("utf-8"); entity.setcontenttype("application/json"); httppost.setentity(entity); } catch (unsupportedencodingexception e) { // todo auto-generated catch block e.printstacktrace(); } return sendhttppost(httppost); }
private string sendhttppost(httppost httppost) { closeablehttpclient httpclient = null; closeablehttpresponse response = null; httpentity entity = null; string responsecontent = null; // 创建默认的httpclient实例 httpclient = httpclients.createdefault(); httppost.setconfig(requestconfig); httppost.setheader("accept","aplication/json"); httppost.addheader("content-type","application/json;charset=utf-8"); // 执行请求 try { logger.info("开始同步数据"); response = httpclient.execute(httppost); entity = response.getentity(); responsecontent = entityutils.tostring(entity, "utf-8"); logger.info("数据同步结果:" + responsecontent); } catch (ioexception e) { logger.error("同步数据出错:" + e.tostring()); e.printstacktrace(); } finally { try { if (response != null) { response.close(); } if (httpclient != null) { httpclient.close(); } } catch (exception e2) { logger.error("流关闭出错:" + e2.tostring()); } } return responsecontent; }
(2)修改后
client端
public string sendhttppost(string httpurl, string data) { // 创建post请求 httppost httppost = new httppost(httpurl); stringentity entity; entity = new stringentity(data,"utf-8"); entity.setcontenttype("application/json"); //entity.setcontenttype(new basicheader(http.content_type, "application/json"));//用这个跟上面一行那个结果一样,可以查看源码 httppost.setentity(entity); return sendhttppost(httppost); } private string sendhttppost(httppost httppost) { closeablehttpclient httpclient = null; closeablehttpresponse response = null; httpentity entity = null; string responsecontent = null; // 创建默认的httpclient实例 httpclient = httpclients.createdefault(); httppost.setconfig(requestconfig); httppost.setheader("accept","aplication/json"); httppost.addheader("content-type","application/json;charset=utf-8"); }
服务端 代码
//服务端 代码 通过红色字体的代码接受数据 public map<string, object> getrequestpostparams(httpservletrequest request) throws businessexception { try { //接收数据 stringbuffer sb = new stringbuffer() ; inputstream is = request.getinputstream(); inputstreamreader isr = new inputstreamreader(is, "utf-8"); bufferedreader br = new bufferedreader(isr); string s = "" ; while((s=br.readline())!=null){ sb.append(s) ; } string strdata = sb.tostring(); if (null == strdata || "".equals(strdata)) { return new hashmap<string, object>(); } map<string, object> params = this.parsejson2map(strdata); return params; } catch(exception e) { throw new businessexception(businessexception.error_inner, "参数转换错误!"); } }
下面来解释原因:
看到这里 发现了client端的不同的吧,没错 只有一行代码不一样
entity = new stringentity(data,"utf-8");
就是这行代码,因为构造方法的不同造成的
本来参考了把问题解决了,但是我发现 我自己的代码明明也设置额编码 为什么会出现乱码呢,于是我就去看源代码的实现,差异在哪里? 下面贴上源代码
public stringentity(final string string, final contenttype contenttype) throws unsupportedcharsetexception { super(); args.notnull(string, "source string"); charset charset = contenttype != null ? contenttype.getcharset() : null; if (charset == null) { charset = http.def_content_charset; } try { this.content = string.getbytes(charset.name()); } catch (final unsupportedencodingexception ex) { // should never happen throw new unsupportedcharsetexception(charset.name()); } if (contenttype != null) { setcontenttype(contenttype.tostring()); } }
然后就发现,在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的同时已经做了字符串的转码操作
之所以说这么多,是想告诉自己,问题解决了固然是好,但应该知道为什么这么做,多看源码,多问自己为什么,仅此共勉。
补充:httpclient post发送json数组并解决json乱码问题
业务:
客户端发送json数据,服务端进行解析
client发送json格式:
{"data":[{"name":"1;,a","id_no":"222,a","cellphone":"123141a","abode_detail":"213,a","emp_add":"werew3a","app_no":"111111111111a","create_time":"11a"},{"name":"张三","id_no":"null","cellphone":"null","abode_detail":"null","emp_add":"null","app_no":"null","create_time":"null"},{"name":"1;,","id_no":"222,","cellphone":"123141","abode_detail":"213,","emp_add":"werew3","app_no":"111111111111","create_time":"11"},{"name":"1;,ab","id_no":"222,ab","cellphone":"123141ab","abode_detail":"213,ab","emp_add":"werew3ab","app_no":"111111111111ab","create_time":"11ab"}],"sendtime":"20160503"}
废话少说,直接上主要代码
client端
package msxf.until; import com.fasterxml.jackson.core.jsonprocessingexception; import com.fasterxml.jackson.databind.objectmapper; import msxf.until.model.people; import org.apache.http.httpstatus; import org.apache.http.client.clientprotocolexception; import org.apache.http.client.methods.closeablehttpresponse; import org.apache.http.client.methods.httpurirequest; import org.apache.http.client.methods.requestbuilder; import org.apache.http.entity.stringentity; import org.apache.http.impl.client.closeablehttpclient; import org.apache.http.impl.client.defaulthttprequestretryhandler; import org.apache.http.impl.client.httpclientbuilder; import org.apache.http.message.basicheader; import org.apache.http.protocol.http; import java.io.ioexception; import java.io.unsupportedencodingexception; import java.util.hashmap; import java.util.list; import java.util.map; /** * created by 小省. */ public class main { private final static org.apache.log4j.logger logger =org.apache.log4j.logger.getlogger(main.class); public static void main(string[] args) { map ma=new hashmap(); ma.put("sendtime","20160503"); //连接impala查库,返回list<people>,其中peopel为自定义实体类 list<people> peoplelist=impalajdbc.connimpala(); if(peoplelist.size()==0){ logger.info("peoplelist.size()==0"); } ma.put("data",peoplelist); objectmapper om=new objectmapper(); try { string jsonstr=om.writevalueasstring(ma); system.out.println(jsonstr); closeablehttpresponse httpresponse=null; closeablehttpclient httpclient= httpclientbuilder.create().setretryhandler(new defaulthttprequestretryhandler()).build(); //解决中文乱码,注意与服务端同时存在 stringentity stringentity=new stringentity(jsonstr,"utf-8"); //就目前来说下面这段代码是可有可无 stringentity.setcontentencoding(new basicheader(http.content_type, "application/json")); //post 地址 httpurirequest httpurirequest= requestbuilder.post("http://localhost:8080/qc").setentity(stringentity).build(); httpresponse=httpclient.execute(httpurirequest); system.out.println("发送"); int statuscode=httpresponse.getstatusline().getstatuscode(); if(statuscode== httpstatus.sc_ok){ // httpentity entity = httpresponse.getentity(); // inputstream in =entity.getcontent(); system.out.println("文件传输服务器正常响应!"); } } catch (jsonprocessingexception e) { e.printstacktrace(); } catch (unsupportedencodingexception e) { e.printstacktrace(); } catch (clientprotocolexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } } }
服务端
采用最原始的servlet
import org.apache.http.protocol.http; import org.json.jsonarray; import org.json.jsonexception; import org.json.jsonobject; import java.io.bufferedreader; import java.io.ioexception; import java.io.inputstreamreader; import java.net.urldecoder; /** * created by 小省. */ public class qcservlet extends javax.servlet.http.httpservlet { protected void dopost(javax.servlet.http.httpservletrequest request, javax.servlet.http.httpservletresponse response) throws javax.servlet.servletexception, ioexception { doget(request,response); } protected void doget(javax.servlet.http.httpservletrequest request, javax.servlet.http.httpservletresponse response) throws javax.servlet.servletexception, ioexception { system.out.println("+++++++++++++++++++"); //解决中文乱码 bufferedreader br =new bufferedreader(new inputstreamreader(request.getinputstream(),"utf-8")); string line=null; stringbuffer sb =new stringbuffer(); while ((line=br.readline())!=null){ sb.append(line); } system.out.println("sb.tostring()"+sb.tostring()); //就目前而言string reesult = urldecoder.decode(sb.tostring(), http.utf_8);是可有可无的,httpclient会自动解码 //string reesult =sb.tostring(); string reesult = urldecoder.decode(sb.tostring(), http.utf_8); try { //将string 字符串转化为json数组,并且遍历 jsonobject jsonobject =new jsonobject(reesult); string mesage=(string) jsonobject.getstring("data"); jsonarray myjsonarray = new jsonarray(mesage); for(int i=0 ; i < myjsonarray.length() ;i++){ //获取每一个jsonobject对象 jsonobject myjobject = myjsonarray.getjsonobject(i); system.out.println(myjobject.getstring("name")); } system.out.println(reesult); } catch (jsonexception e) { e.printstacktrace(); } } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。
上一篇: iis7.5 批量删除处理程序映射的方法
下一篇: 高德地图如何查询核酸检测机构点?