我们的项目中通常不可避免的会与第三方系统做交互,这个时候就需要用到一些http工具类,因为对于每一个不同的业务需求我们关注的是入参和出参,至于中间的步骤,比如创建客户端,填充参数等等,我们是不需要关心的,那么这个时候封装一个工具类就很有必要了,尤其是最近经历的一个项目里面,发送http请求竟然用了五中不同的玩法(okhttp、apachehttpclients、hutool、原生的jdk自带的客户端、restTemplate),让我很是无语,于是自己基于apachehttpclients写了一个封装的工具类,废话不多说,直接上代码:
package org.example.http;
import cn.hutool.core.util.HexUtil;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.http.Header;
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.methods.HttpRequestBase;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class HttpRequestUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(HttpRequestUtil.class);
/**
* 设置请求头
*
* @param request
* @param header
*/
private static void setHeader(HttpRequestBase request, Map<String, String> header) {
if (null != header && !header.isEmpty()) {
for (Map.Entry<String, String> stringStringEntry : header.entrySet()) {
request.addHeader(stringStringEntry.getKey(), stringStringEntry.getValue());
}
}
}
/**
* 发送请求,返回结果
*
* @param httpClient
* @param requestBase
* @return
*/
private static String execAndResolveResponse(CloseableHttpClient httpClient, HttpRequestBase requestBase) {
String result = "{}";
try {
CloseableHttpResponse execute = httpClient.execute(requestBase);
HttpEntity responseEntity = execute.getEntity();
result = EntityUtils.toString(responseEntity, Charset.forName("utf-8"));
} catch (Exception e) {
LOGGER.error("execute request exception", e);
}
return result;
}
/**
* raw方式发送请求
*/
public static String doPost(String url, Map<String, String> header, String jsonParam) {
String result = "{}";
try {
//构造post
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
//设置header
setHeader(httpPost, header);
StringEntity stringEntity = new StringEntity(jsonParam, ContentType.APPLICATION_JSON);
//设置请求参数
httpPost.setEntity(stringEntity);
//发送请求
result = execAndResolveResponse(httpClient, httpPost);
} catch (Exception e) {
LOGGER.error("url:{},header:{},params{}", url, JSON.toJSONString(header), jsonParam);
LOGGER.error(result);
LOGGER.error("cn.tk.cloud.common.util.HttpRequestUtil.doPost exception", e);
}
return result;
}
/**
* 表单方式发送请求
*
* @param url
* @param header
* @param formData
* @return
*/
public static String doPost(String url, Map<String, String> header, Map<String, Object> formData) {
String result = "{}";
try {
//构造post
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
//设置header
setHeader(httpPost, header);
//设置params
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(Charset.forName("utf-8"));
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
for (Map.Entry<String, Object> stringObjectEntry : formData.entrySet()) {
builder.addTextBody(stringObjectEntry.getKey(), stringObjectEntry.getValue().toString(), ContentType.create("text/plain", "utf-8"));
}
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
//发送请求
result = execAndResolveResponse(httpClient, httpPost);
} catch (Exception e) {
LOGGER.error("url:{},header:{},formData{}", url, JSON.toJSONString(header), formData);
LOGGER.error(result);
LOGGER.error("cn.tk.cloud.common.util.HttpRequestUtil.doPost exception", e);
}
return result;
}
public static String doPostV2(String url, Map<String, String> header, Map<String, String> formData) {
String result = "{}";
try {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
setHeader(httpPost, header);
List<NameValuePair> params = new ArrayList<>();
for (Map.Entry<String, String> entry : formData.entrySet()) {
params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
httpPost.setEntity(entity);
result = execAndResolveResponse(httpClient, httpPost);
} catch (Exception e) {
LOGGER.error("url:{},header:{},formData{}", url, JSON.toJSONString(header), formData);
LOGGER.error(result);
LOGGER.error("cn.tk.cloud.common.util.HttpRequestUtil.doPost exception", e);
}
return result;
}
/**
* get请求
*/
public static String doGet(String url, Map<String, String> header) {
String result = "{}";
try {
//构造get
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
//设置header
setHeader(httpGet, header);
//发送请求
result = execAndResolveResponse(httpClient, httpGet);
} catch (Exception e) {
LOGGER.error("url:{},header:{}", url, JSON.toJSONString(header));
LOGGER.error(result);
LOGGER.error("cn.tk.cloud.common.util.HttpRequestUtil.doGet exception", e);
}
return result;
}
/**
* hutool的上传不好使,所以这里改用apache httpclients做上传
* file:表单提交文件的变量名
* fileName:文件名
* fileData:文件字节数组
* params:表单其他数据
*/
public static String doUpload(String url, Map<String, String> header, String file, String fileName, byte[] fileData, Map<String, Object> params) {
String result = "{}";
try {
//构造post
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
//设置header
setHeader(httpPost, header);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(Charset.forName("utf-8"));
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody(file, fileData, ContentType.MULTIPART_FORM_DATA, fileName);
for (Map.Entry<String, Object> stringObjectEntry : params.entrySet()) {
builder.addTextBody(stringObjectEntry.getKey(), stringObjectEntry.getValue().toString(), ContentType.create("text/plain", "utf-8"));
}
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
result = execAndResolveResponse(httpClient, httpPost);
} catch (Exception e) {
LOGGER.error("url:{},header:{},fileName{}", url, JSON.toJSONString(header), file);
LOGGER.error(result);
LOGGER.error("cn.tk.cloud.common.util.HttpRequestUtil.doUpload exception", e);
}
return result;
}
/**
* 上传文件,这个方法只上传文件字节数组数据,不是表单的那种上传
*/
public static String doUpload(String url, Map<String, String> header, byte[] fileData) {
String result = "{}";
try {
//构造post
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
//设置header
setHeader(httpPost, header);
HttpEntity entity = new ByteArrayEntity(fileData);
httpPost.setEntity(entity);
result = execAndResolveResponse(httpClient, httpPost);
} catch (Exception e) {
LOGGER.error("url:{},header:{},fileData{}", url, JSON.toJSONString(header), HexUtil.encodeHexStr(fileData));
LOGGER.error(result);
LOGGER.error("cn.tk.cloud.common.util.HttpRequestUtil.doUpload exception", e);
}
return result;
}
/**
* get请求,返回InputStream
*/
public static InputStream doGetInputStream(String url, Map<String, String> header) {
InputStream inputStream = null;
try {
//构造get
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
//设置header
setHeader(httpGet, header);
//发送请求
CloseableHttpResponse execute = httpClient.execute(httpGet);
HttpEntity entity = execute.getEntity();
return entity.getContent();
} catch (Exception e) {
LOGGER.error("url:{},header:{}", url, JSON.toJSONString(header));
LOGGER.error("cn.tk.cloud.common.util.HttpRequestUtil.doGet exception", e);
}
return inputStream;
}
/**
* raw方式发送请求,同时返回responseHeader当中指定的key
*/
public static Pair<String, String> doPost(String url, Map<String, String> header, String jsonParam, String responseHeaderKey) {
String result = "{}";
String targetHeader = "";
try {
//构造post
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
//设置header
setHeader(httpPost, header);
StringEntity stringEntity = new StringEntity(jsonParam, ContentType.APPLICATION_JSON);
//设置请求参数
httpPost.setEntity(stringEntity);
//发送请求
CloseableHttpResponse execute = httpClient.execute(httpPost);
Header firstHeader = execute.getLastHeader(responseHeaderKey);
targetHeader = null == firstHeader ? "" : firstHeader.getValue();
HttpEntity responseEntity = execute.getEntity();
result = EntityUtils.toString(responseEntity, Charset.forName("utf-8"));
} catch (Exception e) {
LOGGER.error("url:{},header:{},params:{},responseHeaderKey:{}", url, JSON.toJSONString(header), jsonParam, responseHeaderKey);
LOGGER.error(result);
LOGGER.error("cn.tk.cloud.common.util.HttpRequestUtil.doPost exception", e);
}
Pair<String, String> pair = new ImmutablePair(result, targetHeader);
return pair;
}
}
下面是pom依赖:
<dependency>
<groupId>com.alibaba.</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.20</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
其实最开始我是想基于hutool封装的,但是表单上传的那个方法试了,文件传不上去,没找到问题,就放弃了