解決使用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(); } } }
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。如有錯誤或未考慮完全的地方,望不吝賜教。
推薦閱讀:
- java HttpClient傳輸json格式的參數實例講解
- Java HttpClient用法的示例詳解
- HttpClient詳細使用示例代碼
- Java利用httpclient通過get、post方式調用https接口的方法
- 解決HttpPost+json請求—服務器中文亂碼及其他問題