解决使用httpclient传递json数据乱码的问题
今天用httpclient传输json数据,服务端接受数据中文乱码,下面分别贴上修改前与修改后的代码以及原因分析
(1)修改前:
client端
publicStringsendHttpPost(StringhttpUrl,Stringdata){
//创建post请求
HttpPosthttpPost=newHttpPost(httpUrl);
StringEntityentity;
try{
entity=newStringEntity(data);
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
}catch(UnsupportedEncodingExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
returnsendHttpPost(httpPost);
}
privateStringsendHttpPost(HttpPosthttpPost){
CloseableHttpClienthttpClient=null;
CloseableHttpResponseresponse=null;
HttpEntityentity=null;
StringresponseContent=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(IOExceptione){
logger.error("同步数据出错:"+e.toString());
e.printStackTrace();
}finally{
try{
if(response!=null){
response.close();
}
if(httpClient!=null){
httpClient.close();
}
}catch(Exceptione2){
logger.error("流关闭出错:"+e2.toString());
}
}
returnresponseContent;
}
(2)修改后
client端
publicStringsendHttpPost(StringhttpUrl,Stringdata){
//创建post请求
HttpPosthttpPost=newHttpPost(httpUrl);
StringEntityentity;
entity=newStringEntity(data,"UTF-8");
entity.setContentType("application/json");
//entity.setContentType(newBasicHeader(HTTP.CONTENT_TYPE,"application/json"));//用这个跟上面一行那个结果一样,可以查看源码
httpPost.setEntity(entity);
returnsendHttpPost(httpPost);
}
privateStringsendHttpPost(HttpPosthttpPost){
CloseableHttpClienthttpClient=null;
CloseableHttpResponseresponse=null;
HttpEntityentity=null;
StringresponseContent=null;
//创建默认的httpclient实例
httpClient=HttpClients.createDefault();
httpPost.setConfig(requestConfig);
httpPost.setHeader("Accept","aplication/json");
httpPost.addHeader("Content-Type","application/json;charset=UTF-8");
}
服务端代码
//服务端代码通过红色字体的代码接受数据 publicMapgetRequestPostParams(HttpServletRequestrequest)throwsBusinessException{ try{ //接收数据 StringBuffersb=newStringBuffer(); InputStreamis=request.getInputStream(); InputStreamReaderisr=newInputStreamReader(is,"utf-8"); BufferedReaderbr=newBufferedReader(isr); Strings=""; while((s=br.readLine())!=null){ sb.append(s); } StringstrData=sb.toString(); if(null==strData||"".equals(strData)){ returnnewHashMap (); } Map params=this.parseJSON2Map(strData); returnparams; }catch(Exceptione){ thrownewBusinessException(BusinessException.ERROR_INNER,"参数转换错误!"); } }
下面来解释原因:
看到这里发现了client端的不同的吧,没错只有一行代码不一样
entity=newStringEntity(data,"UTF-8");
就是这行代码,因为构造方法的不同造成的
本来参考了这篇文章把问题解决了,但是我发现我自己的代码明明也设置额编码为什么会出现乱码呢,于是我就去看源代码的实现,差异在哪里?下面贴上源代码
publicStringEntity(finalStringstring,finalContentTypecontentType)throwsUnsupportedCharsetException{
super();
Args.notNull(string,"Sourcestring");
Charsetcharset=contentType!=null?contentType.getCharset():null;
if(charset==null){
charset=HTTP.DEF_CONTENT_CHARSET;
}
try{
this.content=string.getBytes(charset.name());
}catch(finalUnsupportedEncodingExceptionex){
//shouldneverhappen
thrownewUnsupportedCharsetException(charset.name());
}
if(contentType!=null){
setContentType(contentType.toString());
}
}
然后就发现,在newStringEntity的时候,就已经将数据根据编码进行了处理,也就是说,如果你调用newStringEntity(Stringstring)此构造方法,就会使用其默认的编码进行转码(ISO-8859-1),无论你后面设置多少次(
entity.setContentEncoding("UTF-8");
或者
httpPost.addHeader("Content-Type","application/json;charset=UTF-8");
都不会改变字符串已经被按转码变成Byte[]数组的事实,当然在请求中设定传输编码格式还是要做的。
其实说这么多,解决问题的关键就一句话,在newStringEntity()的时候指定编码就解决了,因为在new的同时已经做了字符串的转码操作
之所以说这么多,是想告诉自己,问题解决了固然是好,但应该知道为什么这么做,多看源码,多问自己为什么,仅此共勉。
补充:httpclientpost发送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端
packagemsxf.until;
importcom.fasterxml.jackson.core.JsonProcessingException;
importcom.fasterxml.jackson.databind.ObjectMapper;
importmsxf.until.model.People;
importorg.apache.http.HttpStatus;
importorg.apache.http.client.ClientProtocolException;
importorg.apache.http.client.methods.CloseableHttpResponse;
importorg.apache.http.client.methods.HttpUriRequest;
importorg.apache.http.client.methods.RequestBuilder;
importorg.apache.http.entity.StringEntity;
importorg.apache.http.impl.client.CloseableHttpClient;
importorg.apache.http.impl.client.DefaultHttpRequestRetryHandler;
importorg.apache.http.impl.client.HttpClientBuilder;
importorg.apache.http.message.BasicHeader;
importorg.apache.http.protocol.HTTP;
importjava.io.IOException;
importjava.io.UnsupportedEncodingException;
importjava.util.HashMap;
importjava.util.List;
importjava.util.Map;
/**
*Createdby小省.
*/
publicclassMain{
privatefinalstaticorg.apache.log4j.Loggerlogger=org.apache.log4j.Logger.getLogger(Main.class);
publicstaticvoidmain(String[]args){
Mapma=newHashMap();
ma.put("sendtime","20160503");
//连接impala查库,返回List,其中peopel为自定义实体类
ListpeopleList=ImpalaJdbc.connImpala();
if(peopleList.size()==0){
logger.info("peopleList.size()==0");
}
ma.put("data",peopleList);
ObjectMapperom=newObjectMapper();
try{
StringjsonStr=om.writeValueAsString(ma);
System.out.println(jsonStr);
CloseableHttpResponsehttpResponse=null;
CloseableHttpClienthttpClient=HttpClientBuilder.create().setRetryHandler(newDefaultHttpRequestRetryHandler()).build();
//解决中文乱码,注意与服务端同时存在
StringEntitystringEntity=newStringEntity(jsonStr,"UTF-8");
//就目前来说下面这段代码是可有可无stringEntity.setContentEncoding(newBasicHeader(HTTP.CONTENT_TYPE,"application/json"));
//post地址
HttpUriRequesthttpUriRequest=RequestBuilder.post("http://localhost:8080/qc").setEntity(stringEntity).build();
httpResponse=httpClient.execute(httpUriRequest);
System.out.println("发送");
intstatusCode=httpResponse.getStatusLine().getStatusCode();
if(statusCode==HttpStatus.SC_OK){
//HttpEntityentity=httpResponse.getEntity();
//InputStreamin=entity.getContent();
System.out.println("文件传输服务器正常响应!");
}
}catch(JsonProcessingExceptione){
e.printStackTrace();
}catch(UnsupportedEncodingExceptione){
e.printStackTrace();
}catch(ClientProtocolExceptione){
e.printStackTrace();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
服务端
采用最原始的servlet
importorg.apache.http.protocol.HTTP;
importorg.json.JSONArray;
importorg.json.JSONException;
importorg.json.JSONObject;
importjava.io.BufferedReader;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjava.net.URLDecoder;
/**
*Createdby小省.
*/
publicclassQcServletextendsjavax.servlet.http.HttpServlet{
protectedvoiddoPost(javax.servlet.http.HttpServletRequestrequest,javax.servlet.http.HttpServletResponseresponse)throwsjavax.servlet.ServletException,IOException{
doGet(request,response);
}
protectedvoiddoGet(javax.servlet.http.HttpServletRequestrequest,javax.servlet.http.HttpServletResponseresponse)throwsjavax.servlet.ServletException,IOException{
System.out.println("+++++++++++++++++++");
//解决中文乱码
BufferedReaderbr=newBufferedReader(newInputStreamReader(request.getInputStream(),"UTF-8"));
Stringline=null;
StringBuffersb=newStringBuffer();
while((line=br.readLine())!=null){
sb.append(line);
}
System.out.println("sb.toString()"+sb.toString());
//就目前而言Stringreesult=URLDecoder.decode(sb.toString(),HTTP.UTF_8);是可有可无的,httpclient会自动解码
//Stringreesult=sb.toString();
Stringreesult=URLDecoder.decode(sb.toString(),HTTP.UTF_8);
try{
//将string字符串转化为json数组,并且遍历
JSONObjectjsonObject=newJSONObject(reesult);
Stringmesage=(String)jsonObject.getString("data");
JSONArraymyJsonArray=newJSONArray(mesage);
for(inti=0;i
以上为个人经验,希望能给大家一个参考,也希望大家多多支持毛票票。如有错误或未考虑完全的地方,望不吝赐教。