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

否则接收到的参数就是乱码

猜你喜欢

转载自www.cnblogs.com/libin6505/p/9817034.html