文章目录
- 1 摘要
- 2 Maven 依赖
- 3 HttpClient 网络请求工具类
- 4 应用与测试
- 4.1 测试类
- 4.2 GET 请求测试
- 4.3 POST 请求-URL拼接参数
- 4.4 POST请求-JSON参数
- 4.5 POST请求-文件上传
- 5 参考资料推荐
- 6 Github 源码
1 摘要
java 项目中网络请求是一个常用的功能。jdk 自带的网络工具类(java.net
)效率低下,因此推荐使用第三方的网络库。Apache HttpClient 库深受广大开发者的欢迎。本文将介绍在 Spring Boot 2.X 项目中简单使用基于 Apache Httpclient 4.5.X 发送请求与上传文件。
2 Maven 依赖
../pom.xml
../demo-common/pom.xml
<!-- Apache httpClient -->
<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>
其中的版本为:
<httpclient.version>4.5.6</httpclient.version>
3 HttpClient 网络请求工具类
../demo-common/src/main/java/com/ljq/demo/springboot/common/util/SimpleHttpClientUtil.java
package com.ljq.demo.springboot.common.util;
import org.apache.http.Consts;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
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.HttpClients;
import org.apache.http.protocol.HTTP;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Map;
/**
* @Description: 网络请求工具类--Powered by Apache HttpClient
* @Author: junqiang.lu
* @Date: 2019/5/16
*/
public class SimpleHttpClientUtil implements Serializable {
private static final long serialVersionUID = 4634161754990919271L;
private static volatile HttpClient httpClient;
private SimpleHttpClientUtil(){}
/**
* GET 方式请求
* 参数通过 url 拼接
*
* @param host 请求地址
* @param path 接口路径
* @param paramsMap 请求参数
* @return
* @throws IOException
*/
public static HttpResponse doGet(String host, String path, Map<String, String> paramsMap) throws IOException {
initHttpClient();
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(10000)
.setConnectTimeout(5000)
.build();
HttpGet httpGet = new HttpGet(getRequestUrl(host, path, paramsMap));
httpGet.setConfig(requestConfig);
httpGet.setHeader(HTTP.CONTENT_TYPE,ContentType.create(ContentType.APPLICATION_FORM_URLENCODED
.getMimeType(),Consts.UTF_8).toString());
return httpClient.execute(httpGet);
}
/**
* POST 方式请求
* 参数通过 url 拼接
*
* @param host 请求地址
* @param path 接口路径
* @param paramsMap 请求参数
* @return
* @throws IOException
*/
public static HttpResponse doPost(String host, String path, Map<String, String> paramsMap) throws IOException {
initHttpClient();
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(10000)
.setConnectTimeout(5000)
.build();
HttpPost httpPost = new HttpPost(getRequestUrl(host, path, paramsMap));
httpPost.setConfig(requestConfig);
httpPost.setHeader(HTTP.CONTENT_TYPE,ContentType.create(ContentType.APPLICATION_FORM_URLENCODED
.getMimeType(),Consts.UTF_8).toString());
return httpClient.execute(httpPost);
}
/**
* POST 方式请求
* 参数通过 Body 传送,JSON 格式
*
* @param host 请求地址
* @param path 接口路径
* @param jsonParams 请求参数(json 字符串)
* @return
*/
public static HttpResponse doPost(String host, String path, String jsonParams) throws IOException {
initHttpClient();
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(10000)
.setConnectTimeout(5000)
.build();
HttpPost httpPost = new HttpPost(host + path);
StringEntity stringentity = new StringEntity(jsonParams, ContentType.APPLICATION_JSON);
httpPost.setEntity(stringentity);
httpPost.setConfig(requestConfig);
httpPost.addHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
return httpClient.execute(httpPost);
}
/**
* POST 方式请求
* 文件上传
*
* @param host 请求地址
* @param path 接口路径
* @param paramsMap 请求参数
* @param fileInputStream 待上传文件流
* @param name 文件对应字段名
* @param fileOriginalName 原始文件名
* @return
*/
public static HttpResponse doPost(String host, String path, Map<String, String> paramsMap,
InputStream fileInputStream, String name, String fileOriginalName) throws IOException {
initHttpClient();
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(10000)
.setConnectTimeout(5000)
.build();
HttpPost httpPost = new HttpPost(host + path);
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
// 解决中文文件名乱码问题
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entityBuilder.setCharset(Consts.UTF_8);
ContentType contentType = ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), Consts.UTF_8);
for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
entityBuilder.addTextBody(entry.getKey(), entry.getValue(), contentType);
}
if (fileInputStream != null && name != null && fileOriginalName != null) {
entityBuilder.addBinaryBody(name, fileInputStream, ContentType.DEFAULT_BINARY, fileOriginalName);
}
httpPost.setEntity(entityBuilder.build());
httpPost.setConfig(requestConfig);
return httpClient.execute(httpPost);
}
/**
* 初始化 httpClient
* @return
*/
private static HttpClient initHttpClient() {
if (httpClient == null) {
synchronized (SimpleHttpClientUtil.class) {
if (httpClient == null) {
httpClient = HttpClients.createDefault();
}
}
}
return httpClient;
}
/**
* 获取完整请求地址(包含参数)
* 参数拼接在 url 中
*
* @param host 请求地址
* @param path 接口路径
* @param paramsMap 请求参数
* @return
*/
private static String getRequestUrl(String host, String path, Map<String, String> paramsMap) {
StringBuilder reqUrl = new StringBuilder(host).append(path);
if (paramsMap != null && !paramsMap.isEmpty()) {
StringBuilder params = new StringBuilder();
for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
params.append("&" + entry.getKey() + "=" + entry.getValue());
}
String paramConnector = "?";
if (!host.contains(paramConnector) && !path.contains(paramConnector)) {
reqUrl.append(paramConnector);
reqUrl.append(params.toString().substring(1));
} else {
reqUrl.append(params.toString());
}
}
return reqUrl.toString();
}
}
4 应用与测试
4.1 测试类
../demo-web/src/test/java/com/ljq/demo/springboot/common/util/SimpleHttpClientUtilTest.java
package com.ljq.demo.springboot.common.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class SimpleHttpClientUtilTest {
private static String API_HOST = "http://192.168.100.100:8848";
private static String API_PATH_USER_LIST = "/api/user/list";
private static String API_PATH_USER_LISTS = "/api/user/lists";
private static String API_PATH_COMMON_UPLOAD = "/api/demo/common/upload";
@Test
public void doGet() throws IOException {
String paramsStr = "?demoKey=demoValue";
Map<String, String> paramsMap = new HashMap<>(16);
paramsMap.put("demoMapKey", "demoMapValue");
paramsMap.put("zhTest", "德玛西亚");
HttpResponse httpResponse = SimpleHttpClientUtil.doGet(API_HOST, API_PATH_USER_LIST + paramsStr, paramsMap);
printHttpResponse(httpResponse);
}
@Test
public void doPostJson() throws IOException {
Map<String, String> paramsMap = new HashMap<>(16);
paramsMap.put("demoMapKey", "demoMapValue");
paramsMap.put("zhTest", "德玛西亚");
HttpResponse httpResponse = SimpleHttpClientUtil.doPost(API_HOST, API_PATH_USER_LIST, new ObjectMapper().writeValueAsString(paramsMap));
printHttpResponse(httpResponse);
}
@Test
public void doPostUrl() throws IOException {
Map<String, String> paramsMap = new HashMap<>(16);
paramsMap.put("demoMapKey", "demoMapValue");
paramsMap.put("zhTest", "德玛西亚");
HttpResponse httpResponse = SimpleHttpClientUtil.doPost(API_HOST, API_PATH_USER_LISTS, paramsMap);
printHttpResponse(httpResponse);
}
@Test
public void doPostMultipart() throws IOException {
Map<String, String> paramsMap = new HashMap<>(16);
paramsMap.put("demoMapKey", "demoMapValue");
paramsMap.put("zhTest", "德玛西亚");
Path path = Paths.get("F:\\download\\阿里巴巴Java开发手册(详尽版).pdf");
String name = "file";
String fileOriginalName = "阿里巴巴Java开发手册(详尽版).pdf";
HttpResponse httpResponse = SimpleHttpClientUtil.doPost(API_HOST, API_PATH_COMMON_UPLOAD, paramsMap,
Files.newInputStream(path),name, fileOriginalName);
printHttpResponse(httpResponse);
}
/**
* 打印 http 请求结果
*
* @param httpResponse
* @throws IOException
*/
public static void printHttpResponse(HttpResponse httpResponse) throws IOException {
System.out.println("response Code: " + httpResponse.getStatusLine().getStatusCode());
System.out.println(EntityUtils.toString(httpResponse.getEntity()));
}
}
4.2 GET 请求测试
请求日志:
2019-05-16 19:49:02:919 [http-nio-8848-exec-2] INFO com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 67) -[AOP-LOG-START]
requestMark: ee0a1d50-d943-42aa-ab63-5505f04de027
requestIP: 192.168.100.1
contentType:application/x-www-form-urlencoded; charset=UTF-8
requestUrl: http://192.168.100.100:8848/api/user/list
requestMethod: GET
requestParams: demoKey = demoValue;zhTest = 德玛西亚;demoMapKey = demoMapValue;
targetClassAndMethod: com.ljq.demo.springboot.web.controller.UserController#queryList
返回结果:
response Code: 200
{"code":1000,"msg":"成功","data":[{"id":5,"userName":"liming","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"liming@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":4,"userName":"lily","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"lily@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":3,"userName":"jack","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"jack@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":2,"userName":"bob","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"bob@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":1,"userName":"tom","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"tom@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1}]}
4.3 POST 请求-URL拼接参数
请求日志:
2019-05-16 20:13:28:509 [http-nio-8848-exec-4] INFO com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 67) -[AOP-LOG-START]
requestMark: c7e7d6d0-873b-440e-bb24-270abde33e7f
requestIP: 192.168.100.1
contentType:application/x-www-form-urlencoded; charset=UTF-8
requestUrl: http://192.168.100.100:8848/api/user/lists
requestMethod: POST
requestParams: zhTest = 德玛西亚;demoMapKey = demoMapValue;
targetClassAndMethod: com.ljq.demo.springboot.web.controller.UserController#queryLists
返回结果:
response Code: 200
{"code":1000,"msg":"成功","data":[{"id":5,"userName":"liming","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"liming@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":4,"userName":"lily","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"lily@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":3,"userName":"jack","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"jack@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":2,"userName":"bob","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"bob@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":1,"userName":"tom","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"tom@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1}]}
4.4 POST请求-JSON参数
请求日志:
2019-05-16 20:15:26:249 [http-nio-8848-exec-5] INFO com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 67) -[AOP-LOG-START]
requestMark: f94612bd-dcc9-4b7b-9c77-2b296cd00948
requestIP: 192.168.100.1
contentType:application/json; charset=UTF-8
requestUrl: http://192.168.100.100:8848/api/user/list
requestMethod: POST
requestParams: {"zhTest":"德玛西亚","demoMapKey":"demoMapValue"}
targetClassAndMethod: com.ljq.demo.springboot.web.controller.UserController#queryList
返回结果:
response Code: 200
{"code":1000,"msg":"成功","data":[{"id":5,"userName":"liming","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"liming@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":4,"userName":"lily","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"lily@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":3,"userName":"jack","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"jack@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":2,"userName":"bob","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"bob@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":1,"userName":"tom","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"tom@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1}]}
4.5 POST请求-文件上传
请求日志:
2019-05-16 20:16:56:569 [http-nio-8848-exec-7] INFO com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 67) -[AOP-LOG-START]
requestMark: 3a4eb27e-c35b-4804-bda1-100c0a1b89d9
requestIP: 192.168.100.1
contentType:multipart/form-data; boundary=-e08loTIIPoPhChkhGqIWqy4J9HX7REn; charset=UTF-8
requestUrl: http://192.168.100.100:8848/api/demo/common/upload
requestMethod: POST
requestParams: zhTest = 德玛西亚;demoMapKey = demoMapValue;fileSize = 1163395;fileContentType = application/octet-stream;fieldName = file;fileOriginalName = 阿里巴巴Java开发手册(详尽版).pdf;
targetClassAndMethod: com.ljq.demo.springboot.web.controller.CommonController#upload
返回参数:
response Code: 200
{"code":1000,"msg":"成功","data":null}