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");
否则接收到的参数就是乱码