集成 HttpClient 实现 HTTP 接口增强
# 集成 HttpClient 实现 HTTP 接口增强
通过集成 Apache HttpClient,可以更灵活、高效地进行 HTTP 请求和响应处理,尤其是在处理大量并发请求时。
# 1. 在 ruoyi-common\pom.xml
添加 HttpClient 依赖
首先,在项目的 pom.xml
文件中添加 HttpClient 依赖:
<!-- HttpClient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version> <!-- 选择适合的版本 -->
</dependency>
1
2
3
4
5
6
2
3
4
5
6
# 2. 创建 Http 配置信息类 HttpConf.java
我们需要一个配置类来管理 HttpClient 的各种超时时间、连接池配置等信息。新建 HttpConf.java
:
package com.ruoyi.common.utils.http;
/**
* Http 配置信息类
*
* 包含所有 HttpClient 的配置信息,包括超时时间、最大连接数、重试次数等。
*
* @author ruoyi
*/
public class HttpConf
{
// 获取连接的最大等待时间(毫秒)
public static int WAIT_TIMEOUT = 10000;
// 连接超时时间(毫秒)
public static int CONNECT_TIMEOUT = 10000;
// 读取超时时间(毫秒)
public static int SO_TIMEOUT = 60000;
// 最大连接数
public static int MAX_TOTAL_CONN = 200;
// 每个路由最大连接数
public static int MAX_ROUTE_CONN = 150;
// 重试次数
public static int RETRY_COUNT = 3;
// 默认 keep-alive 超时时间(毫秒)
public static int KEEP_ALIVE_TIMEOUT = 20000;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 3. 创建连接池清理类 IdleConnectionMonitorThread.java
为了管理和清理连接池中的空闲连接,我们需要一个专门的线程来定期关闭失效的连接。新建 IdleConnectionMonitorThread.java
:
package com.ruoyi.common.utils.http;
import java.util.concurrent.TimeUnit;
import org.apache.http.conn.HttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 连接池清理线程
*
* 该线程定期检查并关闭失效的连接,确保连接池资源的有效利用。
*
* @author ruoyi
*/
public class IdleConnectionMonitorThread extends Thread
{
private static final Logger log = LoggerFactory.getLogger(IdleConnectionMonitorThread.class);
private final HttpClientConnectionManager connMgr;
private volatile boolean shutdown;
public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr)
{
this.connMgr = connMgr;
}
@Override
public void run()
{
try
{
while (!shutdown)
{
synchronized (this)
{
wait(HttpConf.KEEP_ALIVE_TIMEOUT / 4);
connMgr.closeExpiredConnections();
connMgr.closeIdleConnections(HttpConf.KEEP_ALIVE_TIMEOUT, TimeUnit.MILLISECONDS);
}
}
}
catch (InterruptedException e)
{
log.error("连接池清理线程被中断", e);
}
}
public void shutdown()
{
shutdown = true;
synchronized (this)
{
notifyAll();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 4. 修改 HttpUtils.java
类以支持 HttpClient
HttpUtils.java
是 HttpClient 请求的核心实现类。它封装了常见的 GET 和 POST 请求方法,并集成了连接池管理、SSL 支持等功能。以下是修改后的 HttpUtils.java
:
package com.ruoyi.common.utils.http;
import java.io.IOException;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
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.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 通用 HTTP 请求工具类
*
* 封装了 GET 和 POST 请求方法,支持连接池管理和 SSL。
*
* @author ruoyi
*/
public class HttpUtils
{
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
private static RequestConfig requestConfig;
private static CloseableHttpClient httpClient;
private static PoolingHttpClientConnectionManager connMgr;
private static IdleConnectionMonitorThread idleThread;
static
{
initClient();
}
/**
* 初始化 HttpClient 客户端
*/
public synchronized static void initClient()
{
connMgr = new PoolingHttpClientConnectionManager();
connMgr.setMaxTotal(HttpConf.MAX_TOTAL_CONN);
connMgr.setDefaultMaxPerRoute(HttpConf.MAX_ROUTE_CONN);
requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(HttpConf.WAIT_TIMEOUT)
.setConnectTimeout(HttpConf.CONNECT_TIMEOUT)
.setSocketTimeout(HttpConf.SO_TIMEOUT)
.build();
httpClient = HttpClients.custom()
.setConnectionManager(connMgr)
.setDefaultRequestConfig(requestConfig)
.build();
idleThread = new IdleConnectionMonitorThread(connMgr);
idleThread.start();
}
/**
* 发送 GET 请求
*
* @param url 请求 URL
* @return 响应内容
*/
public static String sendGet(String url) throws IOException
{
HttpGet httpGet = new HttpGet(url);
try (CloseableHttpResponse response = httpClient.execute(httpGet))
{
HttpEntity entity = response.getEntity();
return EntityUtils.toString(entity);
}
}
/**
* 发送 POST 请求
*
* @param url 请求 URL
* @param params 请求参数
* @return 响应内容
*/
public static String sendPost(String url, Map<String, Object> params) throws IOException
{
HttpPost httpPost = new HttpPost(url);
// 添加请求参数逻辑略...
try (CloseableHttpResponse response = httpClient.execute(httpPost))
{
HttpEntity entity = response.getEntity();
return EntityUtils.toString(entity);
}
}
/**
* 关闭 HttpClient 客户端
*/
public synchronized static void shutdown()
{
try
{
if (idleThread != null)
{
idleThread.shutdown();
idleThread = null;
}
if (httpClient != null)
{
httpClient.close();
httpClient = null;
}
}
catch (IOException e)
{
log.error("关闭 HttpClient 客户端失败", e);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# 5. 在 ShutdownManager.java
中关闭 HttpClient 连接池
为了确保应用程序在关闭时正确关闭 HttpClient 连接池,修改 ShutdownManager.java
:
package com.ruoyi.framework.manager;
import com.ruoyi.common.utils.http.HttpUtils;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
/**
* 确保应用关闭时释放资源
*/
@Component
public class ShutdownManager
{
@PreDestroy
public void destroy()
{
HttpUtils.shutdown();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 6. 测试集成效果
最后,您可以通过以下代码来测试 HttpClient 的集成效果:
Map<String, Object> paramsMap = new HashMap<>();
paramsMap.put("id", "1");
paramsMap.put("name", "ruoyi");
String responseGet = HttpUtils.sendGet("http://example.com/api/test");
String responsePost = HttpUtils.sendPost("http://example.com/api/test", paramsMap);
System.out.println("GET Response: " + responseGet);
System.out.println("POST Response: " + responsePost);
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 重要 API 和参数说明
- PoolingHttpClientConnectionManager: 管理 HTTP 连接池,优化多线程环境下的连接复用。
- RequestConfig: 配置请求的超时参数,确保在网络波动时应用不会长时间卡死。
- IdleConnectionMonitorThread: 定期清理连接池中失效的连接,防止资源泄漏。
- CloseableHttpClient: HttpClient 的核心接口,提供了发送 HTTP 请求的所有功能。
通过上述步骤,你可以在项目中集成 Apache HttpClient,从而提升 HTTP 请求处理的性能和灵活性。
编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08