解决使用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();

}

}

}

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

以上是 解决使用httpclient传递json数据乱码的问题 的全部内容, 来源链接: utcz.com/z/331959.html

回到顶部