zoukankan      html  css  js  c++  java
  • 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属性,但是如果这样设置,那么Controller方法的返回值只能是String,否则结果无法封装会调用者
            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属性,但是如果这样设置,那么Controller方法的返回值只能是String,否则结果无法封装会调用者
            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属性,但是如果这样设置,那么Controller方法的返回值只能是String,否则结果无法封装会调用者
            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+"	password: "+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+"	password: "+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+"	password: "+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+"	password: "+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"

    这样才能保证请求端接收到的结果中的中文编码正确

    但是,如果请求端设置了 Accept header ,那么Controller的方法的返回值 只能是 String类型,否则结果无法封装会调用者,

    所有强烈建议不要这样做,最好还是在 Controller端返回值为字符串时,设置 produces 属性

    2、对于带参数的 get 请求,必须在服务端 Controller 中进行字符串转码 例如:

      username = new String(username.getBytes("iso8859-1"), "utf-8");

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

  • 相关阅读:
    firefox和ie下面的初始化checkbox
    全球宽带排名出炉 韩国第一中国未入榜(附表)
    逆向查询所有父栏目
    js的点点滴滴
    Treeview绑定数据源 层叠结构数据源的应用
    asp.net读取服务器端文件夹列表
    Treeview绑定数据源 层叠结构数据源的应用(续--完善篇)
    VC数据类型
    jQuery核心文档(翻译中)
    iscroll 下拉刷新,上拉加载
  • 原文地址:https://www.cnblogs.com/libin6505/p/9817034.html
Copyright © 2011-2022 走看看