HttpClient工具类(我改过):

package com.taotao.httpclient;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; 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.ContentType;
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.BasicNameValuePair;
import org.apache.http.util.EntityUtils; public class HttpClientUtil { public static String doGet(String url, Map<String, String> param) { // 创建Httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault(); String resultString = "";
CloseableHttpResponse response = null;
try {
// 创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
URI uri = builder.build(); // 创建http GET请求
HttpGet httpGet = new HttpGet(uri); // 执行请求
response = httpclient.execute(httpGet);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (response != null) {
response.close();
}
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
} public static String doGet(String url) {
return doGet(url, null);
} public static String doPost(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建参数列表
if (param != null) {
List<NameValuePair> paramList = new ArrayList<>();
for (String key : param.keySet()) {
paramList.add(new BasicNameValuePair(key, param.get(key)));
}
// 模拟表单
// UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
// 模拟表单(后面是转码,发送utf8格式的中文)
StringEntity entity = new UrlEncodedFormEntity(paramList,"utf-8");
httpPost.setEntity(entity);
}
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} return resultString;
} public static String doPost(String url) {
return doPost(url, null);
} public static String doPostJson(String url, String json) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建请求内容
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} return resultString;
}
}

工具类的使用测试代码:

package com.taotao.httpclient;

import java.util.HashMap;

import org.junit.Test;

import com.taotao.common.utils.JsonUtils;
import com.taotao.httpclient.HttpClientUtil; public class HTTPClientUtilsTest { //不带参数的get请求
@Test
public void doGet(){ String url = "http://localhost:8083/search/doGet/哈哈";
String doGetResult = HttpClientUtil.doGet(url);
System.out.println("======结果值:"+doGetResult);
} //不带参数的get请求
@Test
public void doGet2(){ String url = "http://localhost:8083/search/doGet2/哈哈";
String doGetResult = HttpClientUtil.doGet(url);
System.out.println("======结果值:"+doGetResult);
} //带参数的get请求
@Test
public void doGetWithParam(){ String url = "http://localhost:8083/search/doGetWithParam";
HashMap<String, String> paramMap = new HashMap<String,String>();
paramMap.put("username", "花千骨");
paramMap.put("password", "123"); String doGetResult = HttpClientUtil.doGet(url,paramMap);
System.out.println("======结果值:"+doGetResult);
} //不带参数的 post 请求
@Test
public void doPost(){ String url = "http://localhost:8083/search/doPost/哈哈";
String doGetResult = HttpClientUtil.doPost(url);
System.out.println("======结果值:"+doGetResult); } //带参数的post请求
@Test
public void doPostWithParam(){ String url = "http://localhost:8083/search/doPostWithParam";
HashMap<String, String> paramMap = new HashMap<String,String>();
paramMap.put("username", "花千骨");
paramMap.put("password", "123"); String doGetResult = HttpClientUtil.doPost(url,paramMap);
System.out.println("======结果值:"+doGetResult); } //带参数的post请求,返回对象
@Test
public void doPostWithParamReturnUser(){ String url = "http://localhost:8083/search/doPostWithParamReturnUser";
HashMap<String, String> paramMap = new HashMap<String,String>();
paramMap.put("username", "花千骨");
paramMap.put("password", "123"); String doGetResult = HttpClientUtil.doPost(url,paramMap);
System.out.println("======结果值:"+doGetResult); } //带参数的post请求,一定要返回String类型
@Test
public void doPostWithParamReturnUser2(){ String url = "http://localhost:8083/search/doPostWithParamReturnUser2";
HashMap<String, String> paramMap = new HashMap<String,String>();
paramMap.put("username", "花千骨");
paramMap.put("password", "123"); String doGetResult = HttpClientUtil.doPost(url,paramMap);
System.out.println("======结果值:"+doGetResult); } //带参数的post请求,参数是json对象,返回User对象
@Test
public void doPostWithJsonParam(){ String url = "http://localhost:8083/search/doPostWithJsonParam";
HashMap<String, String> paramMap = new HashMap<String,String>();
User user = new User();
user.setUsername("花千骨");
user.setPassword("123");
//把对象转为json串
String objectToJson = JsonUtils.objectToJson(user);
//调用发送json对象的post方法
String doGetResult = HttpClientUtil.doPostJson(url,objectToJson);
//======结果值:{"username":"花千骨","passord":"123"}
System.out.println("======结果值:"+doGetResult); } //带参数的post请求,参数是json对象,返回 String 类型
@Test
public void doPostWithJsonParam2(){ String url = "http://localhost:8083/search/doPostWithJsonParam2";
HashMap<String, String> paramMap = new HashMap<String,String>();
User user = new User();
user.setUsername("花千骨");
user.setPassword("123");
//把对象转为json串
String objectToJson = JsonUtils.objectToJson(user);
//调用发送json对象的post方法
String doGetResult = HttpClientUtil.doPostJson(url,objectToJson);
//如果Controller中的RequestMapping上没有加上
// produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8"
//就会有这个乱码返回值: ======结果值:{"username":"???","password":"123"}
//正确返回值:======结果值:{"username":"花千骨","passord":"123"}
System.out.println("======结果值:"+doGetResult); }
}

对应的 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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import com.taotao.common.utils.JsonUtils;
import com.taotao.search.testpojo.User; @Controller
public class HttpClientUtilsController { //无参数的get请求
/**
* 请求方法为:HttpClientUtil.doGet(url)
* 返回值为String类型,requestMapping上必须加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;
} /**
* 请求方法为:HttpClientUtil.doGet(url)
* 返回值为 对象类型,不会乱码,而且一定不能加produces属性,否则结果封装不到调用者
*/
@RequestMapping(value="/doGet2/{pid}")
@ResponseBody
public User doGet2(@PathVariable String pid){
System.out.println("============== "+pid); //这里不会乱码 哈哈
String username = "张三";
String password = "123"; User user = new User();
user.setUsername(username);
user.setPassword(password);
return user;
} //带参数的get请求响应
/**
* 请求方法为:HttpClientUtil.doGet(url,paramMap)
*/
@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请求
/**
* 请求方法为:HttpClientUtil.doPost(url)
*/
@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 请求
/**
* 请求方法为:HttpClientUtil.doPost(url,paramMap)
*/
@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;
} //带参数的post请求,用对象接收,并返回对象的json串
/**
* 请求用的 HttpClientUtil.doPost(url,paramMap)方法,
* 同get请求一样,返回值为 对象类型,不会乱码,而且一定不能加produces属性,否则结果封装不到调用者
*/
@RequestMapping(value="/doPostWithParamReturnUser")
@ResponseBody
public User doPostReturnUser(User user){
System.out.println("===u=== "+user);
return user;
} //带参数的 post请求,用对象接收
/**
* 请求方法为:HttpClientUtil.doPost(url,paramMap))
* 返回值用的String,所以要加 produces 解决中文乱码
*/
@RequestMapping(value="/doPostWithParamReturnUser2",
produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8")
@ResponseBody
public String doPostReturnUser2(User user){
System.out.println("===u=== "+user);
//将user对象转为json串
String result = JsonUtils.objectToJson(user);
return result;
} //带参数的post请求,参数是个json对象
/**
* 请求方法为:HttpClientUtil.doPostJson(url,objectToJson)
*/
@RequestMapping(value="/doPostWithJsonParam")
@ResponseBody
public User doPostWithJsonParam(@RequestBody User user){
System.out.println("===u=== "+user);
return user;
} //带参数的post请求,参数是个json对象
/**
* 注意:请求此方法的httpClient调用的是如下方法
* HttpClientUtil.doPostJson(url,objectToJson)
* 这时,如果在Controller这里方法的返回值不是User对象而是String类型
* 那么必须在RequestMapping上加上
* produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8"
*/
@RequestMapping(value="/doPostWithJsonParam2",
produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8")
@ResponseBody
public String doPostWithJsonParam2(@RequestBody User user){
System.out.println("===u=== "+user);
//将user对象转为json串
String result = JsonUtils.objectToJson(user);
return result;
} }

总结:

主要需要注意的就是下面几点:

1、带参数的get请求,在Controller层中必须对接收到的参数进行转码

//为了避免乱码我们需要转码(带参数的 get 请求,必须在这里转码)
username = new String(username.getBytes("iso8859-1"), "utf-8");

2、在Controller层中,

如果方法的返回值是 String 类型,那么必须在RequestMapping上加上
      produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8"
      否则调用者返回值中的中文会乱码;

如果方法的返回值是 对象 类型,如 User,那么接收参数一般不会乱码,且这时不能在RequestMapping上加
      produces属性,否则,结果不能正确封装到调用者的返回值response中

3、如果Controller层中的方法返回值为String类型,其实可以在请求方的HttpClientUtils工具类中,加上

httpGet.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8"));

这样在 服务层的 Controller 中的Mapping上就可以不用 produces属性,返回值的中文中也不会乱码,

但是这种方法的缺点就是,Controller层方法的返回值类型只能是 String ,如果是 对象 类型,那么就会导致结果无法封装到调用者的返回值中,所以这种方法最好不用,仅供了解(此文中提供的工具类中无此行代码,所以这里的工具类兼容性才更好)。

其他附件代码:

只要保证 发送端 和 服务端 有同样的 User 对象即可:

package com.taotao.search.testpojo;

public class User {

    private String username;
private String password; public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
} @Override
public String toString() {
return "User [username=" + username + ", password=" + password + "]";
}
}

代码中用到的 Json 工具类:

package com.taotao.common.utils;

import java.util.List;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper; public class JsonUtils { // 定义jackson对象
private static final ObjectMapper MAPPER = new ObjectMapper(); /**
* 将对象转换成json字符串。
* <p>Title: pojoToJson</p>
* <p>Description: </p>
* @param data
* @return
*/
public static String objectToJson(Object data) {
try {
String string = MAPPER.writeValueAsString(data);
return string;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
} /**
* 将json结果集转化为对象
*
* @param jsonData json数据
* @param clazz 对象中的object类型
* @return
*/
public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
try {
T t = MAPPER.readValue(jsonData, beanType);
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
} /**
* 将json数据转换成pojo对象list
* <p>Title: jsonToList</p>
* <p>Description: </p>
* @param jsonData
* @param beanType
* @return
*/
public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) {
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
try {
List<T> list = MAPPER.readValue(jsonData, javaType);
return list;
} catch (Exception e) {
e.printStackTrace();
} return null;
} }

HttpClientUntils工具类的使用测试及注意事项(包括我改进的工具类和Controller端的注意事项【附 Json 工具类】)的更多相关文章

  1. Spring统一返回Json工具类,带分页信息

    前言: 项目做前后端分离时,我们会经常提供Json数据给前端,如果有一个统一的Json格式返回工具类,那么将大大提高开发效率和减低沟通成本. 此Json响应工具类,支持带分页信息,支持泛型,支持Htt ...

  2. Spring实现类私有方法测试通用方案

    现实的业务场景中,可能需要对Spring的实现类的私有方法进行测试. 场景描述: 比如XXXService里有 两个函数a.函数b. 而实现类XXXServiceImpl中实现了函数a.函数b,还包含 ...

  3. 22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表。然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法showB输出大写的英文字母表。最后编写主类C,在主类的main方法 中测试类A与类B。

    22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表.然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法sh ...

  4. 用jackson封装的JSON工具类

    package hjp.smart4j.framework.util; import com.fasterxml.jackson.databind.ObjectMapper; import org.s ...

  5. Code片段 : .properties属性文件操作工具类 & JSON工具类

    摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! “贵专” — 泥瓦匠 一.java.util.Properties API & 案例 j ...

  6. Json工具类,实现了反射将整个Object转换为Json对象的功能,支持Hibernate的延迟加

    package com.aherp.framework.util; import java.lang.reflect.Array;import java.lang.reflect.Method;imp ...

  7. Json工具类 - JsonUtils.java

    Json工具类,提供Json与对象之间的转换. 源码如下:(点击下载 - JsonUtils.java . gson-2.2.4.jar ) import java.lang.reflect.Type ...

  8. Java json工具类,jackson工具类,ObjectMapper工具类

    Java json工具类,jackson工具类,ObjectMapper工具类 >>>>>>>>>>>>>>> ...

  9. 小程序入口构造工具&二维码测试工具

    小程序入口构造工具&二维码测试工具 本文将介绍我们小程序中隐藏的两个工具页面.原理虽不复杂,收益却实实在在,或许也能给诸君带来启发. 入口构造工具 痛点 PM&运营 投放链接 PM&a ...

随机推荐

  1. STL——list

    1.关键概述 list 是定义在 namespace::std 的模板,声明在 <list> ,存储结构是 双向链表, 提供的 正向和反向迭代器. 2.构造list对象 list<i ...

  2. mybatis动态列名

    mybatis动态列名 <select id="getUser" resultType="java.util.Map" parameterType=&qu ...

  3. (数据科学学习手札23)决策树分类原理详解&Python与R实现

    作为机器学习中可解释性非常好的一种算法,决策树(Decision Tree)是在已知各种情况发生概率的基础上,通过构成决策树来求取净现值的期望值大于等于零的概率,评价项目风险,判断其可行性的决策分析方 ...

  4. (数据科学学习手札09)系统聚类算法Python与R的比较

    上一篇笔者以自己编写代码的方式实现了重心法下的系统聚类(又称层次聚类)算法,通过与Scipy和R中各自自带的系统聚类方法进行比较,显然这些权威的快捷方法更为高效,那么本篇就系统地介绍一下Python与 ...

  5. 20145202马超 2006-2007-2 《Java程序设计》第3周学习总结

    20145202马超 2016-2017-2 <Java程序设计>第3周学习总结 教材学习内容总结 函数的重载:在同一个类中,允许存在一个以上的同名函数,只要他们的参数数目不同就可以.与返 ...

  6. ubuntu下安装LAMP环境遇到的一些小问题

    0x00 今天在服务器上重新弄了一下lamp环境 安装的过程中遇到了不少小问题 记录一下解决的方案吧 服务器安装的是ubuntu 16.04.1 0x01 首先在用 apt-get install 安 ...

  7. 使用maven插件生成grpc所需要的Java代码

    1.首先需要编写自己需要的.proto文件,本文重点不在这里,.proto可以参考grpc官方例子 https://grpc.io/docs/quickstart/java.html 2.创建自己的J ...

  8. Android各版本代号、版本号、API/NDK级别、发布时间

    代号 版本号 API/NDK级别 发布时间 牛轧糖 Nougat 7.1.2 API level 25 2017-2 7.1.1 2016-10 7.0 API level 24 2016-05 棉花 ...

  9. 【APUE】Chapter10 Signals

    Signal主要分两大部分: A. 什么是Signal,有哪些Signal,都是干什么使的. B. 列举了非常多不正确(不可靠)的处理Signal的方式,以及怎么样设计来避免这些错误出现. 10.2 ...

  10. JavaScript函数constructor的作用,意义

    前几天写了一片 如何用正确的姿势编写jQuery插件 有朋友拍砖,指正.再此谢谢! 讨论:指定函数的constructor作用到底是什么? 我们一般写jQuery插件的时候是这样的: //构造函数 f ...