<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>HttpClient</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<slf4j.version>1.7.36</slf4j.version>
<log4j.version>1.2.17</log4j.version>
<httpclient.version>4.5.14</httpclient.version>
<maven.compiler.plugin.version>3.6.1</maven.compiler.plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>${httpclient.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
</plugin>
</plugins>
</build>
</project>
package com.chenwc.httpclient;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
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.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
/**
* HttpClient 网络请求工具类
* @author chenwc
* @date 2023/5/17 22:25
*/
public class RestMock<K, V> {
private final static Logger log = LoggerFactory.getLogger(RestMock.class);
/**
* Socket 超时时间
*/
private final static Integer SocketTimeout = 20000;
/**
* 连接超时时间
*/
private final static Integer ConnectTimeout = 20000;
/**
* 发起 post 请求,提交文件和表单
* 文件表单格式:form-data; name="file"; filename="xxxxxxxxxx"
* 表单格式:form-data; name="key1"
* 单格式:form-data; name="key2"
*
* @param urlStr http请求的地址
* @param headerMap 头信息
* @param formBodyMap 表单参数
* @param file 文件
* @return 响应信息
*/
public static String sendPostByFileAndFormBody(String urlStr, Map<String, String> headerMap, Map<String, String> formBodyMap, File file) {
log.info("url----------------> " + urlStr);
String sResponse = null;
long t1 = System.currentTimeMillis();
CloseableHttpClient httpClient = null;
try {
// 创建HttpClient
httpClient = getHttpClient(urlStr.startsWith("https"));;
HttpPost httpPost = getHttpPost(urlStr, headerMap);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
//请求的编码格式
builder.setCharset(StandardCharsets.UTF_8);
//浏览器兼容模式
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
FileBody fileBody = new FileBody(file);
builder.addPart("file", fileBody);
//添加表单参数
if (null != formBodyMap && !formBodyMap.isEmpty()){
for (String key : formBodyMap.keySet()) {
StringBody strBody = new StringBody(formBodyMap.get(key), ContentType.MULTIPART_FORM_DATA.withCharset(StandardCharsets.UTF_8));
builder.addPart(key, strBody);
}
}
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
// 执行提交
HttpResponse response = httpClient.execute(httpPost);
sResponse = getResponseMessage(response);
long t2 = System.currentTimeMillis();
log.info("----------请求总用时:{} 秒", ((t2 - t1) / 1000.0));
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
if (null != httpClient) {
httpClient.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return sResponse;
}
/**
* 发起 post 请求,提交表单
* 表单格式:form-data; name="key1"
* 单格式:form-data; name="key2"
*
* @param urlStr http请求的地址
* @param headerMap 头信息
* @param formBodyMap 表单参数
* @return 响应信息
*/
public static String sendPostByFormBody(String urlStr, Map<String, String> headerMap, Map<String, String> formBodyMap) {
log.info("url----------------> " + urlStr);
String sResponse = null;
long t1 = System.currentTimeMillis();
CloseableHttpClient httpClient = null;
try {
// 创建HttpClient
httpClient = getHttpClient(urlStr.startsWith("https"));;
HttpPost httpPost = getHttpPost(urlStr, headerMap);
StringEntity entity = getFormBodyEntity(formBodyMap);
if (null != entity){
httpPost.setEntity(entity);
}
// 执行提交
HttpResponse response = httpClient.execute(httpPost);
sResponse = getResponseMessage(response);
long t2 = System.currentTimeMillis();
log.info("----------请求总用时:{} 秒", ((t2 - t1) / 1000.0));
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
if (null != httpClient) {
httpClient.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return sResponse;
}
/**
* 发起 post 请求,带有请求体
*
* @param urlStr http请求的地址
* @param headerMap 头信息
* @param body 请求体
* @return 响应信息
*/
public static String sendPostByBody(String urlStr, Map<String, String> headerMap, String body) {
log.info("url----------------> " + urlStr);
String sResponse = null;
long t1 = System.currentTimeMillis();
CloseableHttpClient httpClient = null;
try {
// 创建HttpClient
httpClient = getHttpClient(urlStr.startsWith("https"));;
HttpPost httpPost = getHttpPost(urlStr, headerMap);
if (null != body && !body.isEmpty()){
StringEntity entity = new StringEntity(body, StandardCharsets.UTF_8);
httpPost.setEntity(entity);
}
// 执行提交
HttpResponse response = httpClient.execute(httpPost);
sResponse = getResponseMessage(response);
long t2 = System.currentTimeMillis();
log.info("----------请求总用时:{} 秒", ((t2 - t1) / 1000.0));
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
if (null != httpClient) {
httpClient.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return sResponse;
}
/**
* 发起 post 请求
*
* @param urlStr http请求的地址
* @param headerMap 头信息
* @return 响应信息
*/
public static String sendPost(String urlStr, Map<String, String> headerMap) {
return sendPostByBody(urlStr, headerMap, null);
}
/**
* 获取HttpPost
* @param url url
* @param header 头信息
* @return HttpPost
*/
private static HttpPost getHttpPost(String url, Map<String, String> header) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(getRequestConfig());
//装入头信息
if (null != header && !header.isEmpty()) {
for (String key : header.keySet()) {
httpPost.addHeader(key, header.get(key));
}
}
return httpPost;
}
/**
* 发起 get 请求,带有请求参数
*
* @param urlStr http请求的地址
* @param headerMap 头信息
* @param parameterMap 请求参数
* @return 响应信息
*/
public static String sendGetByParameter(String urlStr, Map<String, String> headerMap, Map<String, String> parameterMap) {
log.info("url----------------> " + urlStr);
String sResponse = null;
long t1 = System.currentTimeMillis();
CloseableHttpClient httpClient = null;
try {
// 创建HttpClient
httpClient = getHttpClient(urlStr.startsWith("https"));
HttpGet httpGet = getHttpGet(urlStr, headerMap, parameterMap);
// 执行提交
HttpResponse response = httpClient.execute(httpGet);
sResponse = getResponseMessage(response);
long t2 = System.currentTimeMillis();
log.info("----------请求总用时:{} 秒", ((t2 - t1) / 1000.0));
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
if (null != httpClient) {
httpClient.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return sResponse;
}
/**
* 发起 get 请求
*
* @param urlStr http请求的地址
* @param headerMap 头信息
* @return 响应信息
*/
public static String sendGet(String urlStr, Map<String, String> headerMap) {
return sendGetByParameter(urlStr, headerMap, new HashMap<>());
}
/**
* 使用get请求下载文件
*
* @param urlStr url
* @param filePath 文件保存路径
*/
public static void downloadFileByGet(String urlStr, String filePath) {
log.info("url----------------> " + urlStr);
long t1 = System.currentTimeMillis();
CloseableHttpClient httpClient = null;
InputStream inputStream = null;
FileOutputStream fos = null;
ByteArrayOutputStream bos = null;
File fileExists = new File(filePath);
try {
if (!fileExists.exists()) {
if (!mkdirParents(fileExists)) {
log.info("创建父级目录失败!");
return;
}
if (!fileExists.createNewFile()) {
log.info("创建文件: {} 失败!", filePath);
return;
}
}
// 创建HttpClient
httpClient = getHttpClient(urlStr.contains("https"));
HttpGet httpGet = getHttpGet(urlStr, new HashMap<>(), new HashMap<>());
// 执行提交
HttpResponse response = httpClient.execute(httpGet);
int statusCode = response.getStatusLine().getStatusCode();
log.info("-----------------状态码--------------");
log.info("---------------------->statusCode: " + statusCode);
if (statusCode == 200) {
// 得到实体
HttpEntity entity = response.getEntity();
log.info("开始下载文件....");
inputStream = entity.getContent();
byte[] buffer = new byte[1024];
int len = 0;
bos = new ByteArrayOutputStream();
while ((len = inputStream.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
byte[] getData = bos.toByteArray();
File file = new File(filePath);
fos = new FileOutputStream(file);
fos.write(getData);
log.info("下载文件成功!");
log.info("文件保存到:{}", filePath);
}
long t2 = System.currentTimeMillis();
log.info("----------请求总用时:{} 秒", ((t2 - t1) / 1000.0));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != httpClient) {
httpClient.close();
}
if (null != inputStream) {
inputStream.close();
}
if (null != fos) {
fos.close();
}
if (null != bos) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 获取HttpGet
* @param url url
* @param header 头信息
* @param parameterMap 请求参数
* @return HttpGet
*/
private static HttpGet getHttpGet(String url, Map<String, String> header, Map<String, String> parameterMap) throws UnsupportedEncodingException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
String paramerterString = generateGetParameter(parameterMap);
if (null != parameterMap && !parameterMap.isEmpty()) {
if (url.endsWith("?")) {
url = url + paramerterString;
}
else {
url = url + "?" + paramerterString;
}
}
log.info("getUrl---------------->{}", url);
HttpGet httpGet= new HttpGet(url);
httpGet.setConfig(getRequestConfig());
//装入头信息
if (null != header && !header.isEmpty()) {
for (String key : header.keySet()) {
httpGet.addHeader(key, header.get(key));
}
}
return httpGet;
}
/**
* 根据表单 map 转换成 StringEntity
* @param formBodyMap 表单 map
* @return StringEntity
*/
private static StringEntity getFormBodyEntity(Map<String, String> formBodyMap){
StringEntity entity = null;
List<NameValuePair> kvList = new ArrayList<>();
if (null != formBodyMap && !formBodyMap.isEmpty()){
for (String key : formBodyMap.keySet()) {
kvList.add(new BasicNameValuePair(key, formBodyMap.get(key)));
}
}
if (!kvList.isEmpty()){
// 包装成一个Entity对象
entity = new UrlEncodedFormEntity(kvList, StandardCharsets.UTF_8);
}
return entity;
}
/**
* 获取 http 响应信息
* @param response HttpResponse
* @return 响应信息
* @throws IOException IOException
*/
private static String getResponseMessage(HttpResponse response) throws IOException {
String sResponse = null;
int statusCode = response.getStatusLine().getStatusCode();
log.info("-----------------状态码--------------");
log.info("---------------------->statusCode: " + statusCode);
HttpEntity responseEntity = response.getEntity();
//响应状态码200
if (null != responseEntity) {
// 将响应的内容转换成字符串
sResponse = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
log.info("sResponse:--------------->" + sResponse);
} else {
log.info("响应信息为空!");
}
return sResponse;
}
/**
* 获取 CloseableHttpClient
* @param isDeceive 是否绕过SSL
* @return CloseableHttpClient
*/
private static CloseableHttpClient getHttpClient(boolean isDeceive) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
CloseableHttpClient httpClient;
if (isDeceive){
// 信任所有
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (TrustStrategy) (chain, authType) -> true).build();
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
}
else {
httpClient = HttpClients.createDefault();
}
return httpClient;
}
/**
* 获取 http 请求配置
* @return http 请求配置
*/
private static RequestConfig getRequestConfig() {
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
//设置超时时间,这个是httpclient 4.3版本之后的设置方法
requestConfigBuilder.setConnectTimeout(ConnectTimeout);
requestConfigBuilder.setSocketTimeout(SocketTimeout);
return requestConfigBuilder.build();
}
/**
* 根据map生成get请求参数,格式 A=a&B=b
* @param parameterMap 请求参数map
* @return get请求参数url
*/
private static String generateGetParameter(Map<String, String> parameterMap) throws UnsupportedEncodingException {
StringBuilder sb = new StringBuilder();
if (null != parameterMap) {
Set<String> keySet = parameterMap.keySet();
int index = 1;
for (String key : keySet) {
String value = URLEncoder.encode(parameterMap.get(key), String.valueOf(StandardCharsets.UTF_8));
if(index == keySet.size()) {
sb.append(key).append("=").append(value);
}
else {
sb.append(key).append("=").append(value).append("&");
}
index++;
}
}
return sb.toString();
}
/**
* 判断文件的父级目录是否存在,不存在则创建
*
* @param file 文件
* @return true 父级目录存在或创建父级目录成功, false创建父级目录失败
*/
public static boolean mkdirParents(File file) {
if (!file.getParentFile().exists()) {
return file.getParentFile().mkdirs();
} else {
return true;
}
}
}
log4j.rootLogger=info,stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %-5p %-5L --- [%-5t] %-10c : %m %n
log4j-1.2.17.jar
slf4j-api-1.7.36.jar
slf4j-log4j12-1.7.7.jar
httpmime-4.5.14.jar
httpcore-4.4.14.jar
httpclient-4.5.14.jar
commons-logging-1.2.jar
commons-codec-1.11.jar