欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

解决使用httpclient传递json数据乱码的问题

程序员文章站 2023-01-14 11:08:15
今天用httpclient传输json数据,服务端接受数据 中文乱码,下面分别贴上修改前与修改后的代码以及原因分析(1)修改前:client端 public string sendhttppost(s...

今天用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();
}
}
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。