HttpClient測試類請求端和服務端即可能出現亂碼的解決
阿新 • • 發佈:2018-11-10
junit HttpClient 請求端 程式碼:
package com.taotao.httpclient; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicHeader;import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.junit.Test; public class HTTPClientGTest2 { //不帶引數的get請求 @Test public void doGet() throws Exception { //建立一個可關閉的httpClient物件 CloseableHttpClient httpClient = HttpClients.createDefault();//建立一個get物件 HttpGet get = new HttpGet("http://localhost:8083/search/doGet/哈哈"); //注意,如果請求這裡設定了 Accept header,那麼 服務層的Controller 中的Mapping上就可以不用 produces屬性 get.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8")); //執行請求 CloseableHttpResponse response = httpClient.execute(get); //取響應結果 //先獲取響應碼 int statusCode = response.getStatusLine().getStatusCode(); System.out.println("======響應碼:"+statusCode); //200 //獲取響應結果物件 HttpEntity entity = response.getEntity(); //將結果物件轉換為字串 String string = EntityUtils.toString(entity,"utf-8"); //結果:=======結果值:username: 張三 password: 123 System.out.println("======結果值:"+string); //關閉資源 response.close(); httpClient.close(); } //帶引數的get請求 @Test public void doGetWithParam() throws Exception { //建立一個可關閉的httpClient物件 CloseableHttpClient httpClient = HttpClients.createDefault(); //帶引數方法1:直接拼接在請求中 建立get物件 /*HttpGet get = new HttpGet( "http://localhost:8083/search/doGetWithParam?username=花千骨&password=123");*/ //帶引數方法2 用物件的方式新增引數 //先建立一個基本的(不帶引數的)uri物件 URIBuilder uriBuilder = new URIBuilder("http://localhost:8083/search/doGetWithParam"); uriBuilder.addParameter("username", "花千骨"); uriBuilder.addParameter("password", "123"); //再建立get物件 HttpGet get = new HttpGet(uriBuilder.build()); //注意,如果請求這裡設定了 Accept header,那麼 服務層的Controller 中的Mapping上就可以不用 produces屬性 get.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8")); //執行請求 CloseableHttpResponse response = httpClient.execute(get); //取響應結果 //先獲取響應碼 int statusCode = response.getStatusLine().getStatusCode(); System.out.println("======響應碼:"+statusCode); //獲取響應結果物件 HttpEntity entity = response.getEntity(); //將結果物件轉換為字串 String string = EntityUtils.toString(entity,"utf-8"); //======結果值:username: 花千骨 password: 123 System.out.println("======結果值:"+string); //關閉資源 response.close(); httpClient.close(); } //不帶引數的 post 請求 @Test public void doPost() throws Exception { CloseableHttpClient httpClient = HttpClients.createDefault(); // HttpPost post = new HttpPost("http://localhost:8082/httpclient/post.html"); // 注意:如果請求的url字尾是 .html則瀏覽器不能返回正確的json資料,會返回406錯誤,所以需要修改請求url的字尾為其他 // HttpPost post = new HttpPost("http://localhost:8082/httpclient/post.action"); HttpPost post = new HttpPost("http://localhost:8083/search/doPost/哈哈"); //注意,如果請求這裡設定了 Accept header,那麼 服務層的Controller 中的Mapping上就可以不用 produces屬性 post.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8")); CloseableHttpResponse response = httpClient.execute(post); HttpEntity entity = response.getEntity(); String string = EntityUtils.toString(entity, "utf-8"); System.out.println(string); response.close(); httpClient.close(); } //帶引數的post請求 @Test public void doPostWithParam() throws Exception { CloseableHttpClient httpClient = HttpClients.createDefault(); //建立一個post物件 HttpPost post = new HttpPost("http://localhost:8083/search/doPostWithParam"); //注意,如果請求這裡設定了 Accept header,那麼 服務層的Controller 中的Mapping上就可以不用 produces屬性 post.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8")); //模擬一個表單 List<NameValuePair> kvList = new ArrayList<NameValuePair>(); kvList.add(new BasicNameValuePair("username", "張三")); kvList.add(new BasicNameValuePair("password", "123")); //包裝成一個Entity物件(後面加字符集是為了向服務端傳送資料時不會亂碼) StringEntity paramEntity = new UrlEncodedFormEntity(kvList,"utf-8"); //設定請求內容 post.setEntity(paramEntity); //執行post請求 CloseableHttpResponse response = httpClient.execute(post); HttpEntity rtnEntity = response.getEntity(); String string = EntityUtils.toString(rtnEntity, "utf-8"); System.out.println(string); response.close(); httpClient.close(); } }
對應的 springMVC 的 Controller 端程式碼:
package com.taotao.search.controller; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class HttpClientController { //無引數的get請求 /*prodcues的目的是為了返回給呼叫者時中文不亂碼, * 如果介面呼叫者請求的 http物件設定了 * httpget.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8")); * 那麼這裡服務端可以不加produces,否則必須加 */ @RequestMapping(value="/doGet/{pid}",produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8") @ResponseBody public String doGet(@PathVariable String pid){ System.out.println("============== "+pid); //這裡不會亂碼 哈哈 String username = "張三"; String password = "123"; String result = "username: "+username+"\tpassword: "+password; return result; } //帶引數的get請求響應 /** * 同理,如果 介面呼叫者中 沒有加 setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8") * 這裡必須加上 produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8" */ @RequestMapping(value="/doGetWithParam",produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8") @ResponseBody public String doGetWithParam(String username,String password) throws Exception{ //====== username: è±å骨password: 123 System.out.println("====== username: "+username +"password: "+password); //為了避免亂碼我們需要轉碼(帶引數的 get 請求,必須在這裡轉碼) username = new String(username.getBytes("iso8859-1"), "utf-8"); password = new String(password.getBytes("iso8859-1"), "utf-8"); //===轉碼後=== username: 花千骨password: 123 System.out.println("===轉碼後=== username: "+username +"password: "+password); String result = "username: "+username+"\tpassword: "+password; return result; } //不帶引數的 post請求 @RequestMapping(value="/doPost/{pid}",produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8") @ResponseBody public String doPost(@PathVariable String pid){ System.out.println("============== "+pid); //哈哈 String username = "張三"; String password = "123"; String result = "username: "+username+"\tpassword: "+password; return result; } //帶引數的 post 請求 /** * 同理,如果 介面呼叫者中 沒有加 setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8") * 這裡必須加上 produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8" */ //注意:post請求,後臺服務接收端不用對引數進行轉碼 @RequestMapping(value="/doPostWithParam"/*,produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8"*/) @ResponseBody public String doPost(String username,String password){ //====== username: 張三password: 123 System.out.println("====== username: "+username +"password: "+password); String result = "username: "+username+"\tpassword: "+password; return result; } }
注意項總結:
1、無論哪種請求//注意,如果請求端設定了 Accept header 例如:
httpget.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8"));
那麼 服務層的Controller 中的Mapping上就可以不用 produces屬性,否則服務端的Controller中比如加入:
produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8"
這樣才能保證請求端接收到的結果中的中文編碼正確。
2、對於帶引數的 get 請求,必須在服務端 Controller 中進行字串轉碼 例如:
username = new String(username.getBytes("iso8859-1"), "utf-8");
否則接收到的引數就是亂碼