1. 程式人生 > >HttpClient測試類請求端和服務端即可能出現亂碼的解決

HttpClient測試類請求端和服務端即可能出現亂碼的解決

 

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");

否則接收到的引數就是亂碼