解決使用httpclient傳遞json數(shù)據(jù)亂碼的問題
今天用httpclient傳輸json數(shù)據(jù),服務端接受數(shù)據(jù) 中文亂碼,下面分別貼上修改前與修改后的代碼以及原因分析
(1)修改前:
client端
public String sendHttpPost(String httpUrl, String data) {
// 創(chuàng)建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;
// 創(chuàng)建默認的httpclient實例
httpClient = HttpClients.createDefault();
httpPost.setConfig(requestConfig);
httpPost.setHeader("Accept","aplication/json");
httpPost.addHeader("Content-Type","application/json;charset=UTF-8");
// 執(zhí)行請求
try {
logger.info("開始同步數(shù)據(jù)");
response = httpClient.execute(httpPost);
entity = response.getEntity();
responseContent = EntityUtils.toString(entity, "UTF-8");
logger.info("數(shù)據(jù)同步結果:" + responseContent);
} catch (IOException e) {
logger.error("同步數(shù)據(jù)出錯:" + 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) {
// 創(chuàng)建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;
// 創(chuàng)建默認的httpclient實例
httpClient = HttpClients.createDefault();
httpPost.setConfig(requestConfig);
httpPost.setHeader("Accept","aplication/json");
httpPost.addHeader("Content-Type","application/json;charset=UTF-8");
}
服務端 代碼
//服務端 代碼 通過紅色字體的代碼接受數(shù)據(jù)
public Map<String, Object> getRequestPostParams(HttpServletRequest request) throws BusinessException {
try {
//接收數(shù)據(jù)
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, "參數(shù)轉(zhuǎn)換錯誤!");
}
}
下面來解釋原因:
看到這里 發(fā)現(xiàn)了client端的不同的吧,沒錯 只有一行代碼不一樣
entity = new StringEntity(data,"UTF-8");
就是這行代碼,因為構造方法的不同造成的
本來參考了這篇文章把問題解決了,但是我發(fā)現(xiàn) 我自己的代碼明明也設置額編碼 為什么會出現(xiàn)亂碼呢,于是我就去看源代碼的實現(xiàn),差異在哪里? 下面貼上源代碼
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());
}
}
然后就發(fā)現(xiàn),在new StringEntity的時候,就已經(jīng)將數(shù)據(jù)根據(jù)編碼進行了處理,也就是說,如果你調(diào)用 new StringEntity(String string)此構造方法,就會使用其默認的編碼進行轉(zhuǎn)碼(ISO-8859-1),無論你后面設置多少次(
entity.setContentEncoding("UTF-8");
或者
httpPost.addHeader("Content-Type","application/json;charset=UTF-8");
都不會改變字符串已經(jīng)被按轉(zhuǎn)碼變成Byte[]數(shù)組的事實,當然在請求中設定傳輸編碼格式還是要做的。
其實說這么多 ,解決問題的關鍵就一句話,在new StringEntity()的時候指定編碼就解決了,因為在new的同時已經(jīng)做了字符串的轉(zhuǎn)碼操作
之所以說這么多,是想告訴自己,問題解決了固然是好,但應該知道為什么這么做,多看源碼,多問自己為什么,僅此共勉。
補充:httpclient post發(fā)送json數(shù)組并解決json亂碼問題
業(yè)務:
客戶端發(fā)送json數(shù)據(jù),服務端進行解析
client發(fā)送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("發(fā)送");
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 字符串轉(zhuǎn)化為json數(shù)組,并且遍歷
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();
}
}
}
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關文章
Java搭建簡單Netty開發(fā)環(huán)境入門教程
這篇文章主要介紹了Java搭建簡單Netty開發(fā)環(huán)境入門教程,有詳細的代碼展示和maven依賴,能夠幫助你快速上手Netty開發(fā)框架,需要的朋友可以參考下2021-06-06
MyBatis解決Update動態(tài)SQL逗號的問題
這篇文章主要介紹了MyBatis解決Update動態(tài)SQL逗號的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01

