Skip to content

Commit a785a7d

Browse files
author
littlelory
committed
HTTP请求工具类重写
1 parent 6527b97 commit a785a7d

4 files changed

Lines changed: 339 additions & 126 deletions

File tree

java/HttpClient.java

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
package utils.http;
2+
3+
import org.apache.commons.logging.Log;
4+
import org.apache.commons.logging.LogFactory;
5+
import org.apache.http.*;
6+
import org.apache.http.client.ClientProtocolException;
7+
import org.apache.http.client.HttpResponseException;
8+
import org.apache.http.client.ResponseHandler;
9+
import org.apache.http.client.config.RequestConfig;
10+
import org.apache.http.client.methods.HttpGet;
11+
import org.apache.http.client.methods.HttpPost;
12+
import org.apache.http.conn.ConnectionPoolTimeoutException;
13+
import org.apache.http.conn.HttpClientConnectionManager;
14+
import org.apache.http.entity.ContentType;
15+
import org.apache.http.entity.StringEntity;
16+
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
17+
import org.apache.http.impl.client.HttpClients;
18+
import org.apache.http.message.BasicHeader;
19+
20+
import java.io.BufferedReader;
21+
import java.io.IOException;
22+
import java.io.InputStreamReader;
23+
import java.net.SocketTimeoutException;
24+
import java.nio.charset.Charset;
25+
import java.util.Map;
26+
27+
/**
28+
* HttpClient实体类
29+
* 这个类是对Apache的org.apache.http.client.HttpClient的一层封装
30+
*
31+
* Created by littlelory on 02/11/2017.
32+
*/
33+
public class HttpClient {
34+
private Log log = LogFactory.getLog(HttpClient.class);
35+
36+
//Apache httpclient实例
37+
private org.apache.http.client.HttpClient httpClient;
38+
//client标识
39+
private String key;
40+
41+
private HttpClient(org.apache.http.client.HttpClient httpClient, String key) {
42+
this.httpClient = httpClient;
43+
this.key = key;
44+
}
45+
46+
/**
47+
* post请求
48+
* 向url参数传入的连接发送请求,请求的Body内容由body参数决定
49+
*
50+
* @param url 请求url
51+
* @param headerMap http header数据,key为header名,value为header值
52+
* @param body 请求的Body内容
53+
* @return 响应数据
54+
* @throws IOException 请求过程中发生异常
55+
*/
56+
public String doPost(String url, Map<String, String> headerMap, String body) throws IOException {
57+
log.info("[httpclient]["+key+"] to post, url = [" + url + "], headerMap = [" + headerMap + "], body = [" + body + "].");
58+
59+
//创建请求实例
60+
HttpPost request = new HttpPost(url);
61+
62+
//设置Headers
63+
if (headerMap != null && headerMap.size() > 0) {
64+
int headerSize = headerMap.size();
65+
Header[] headers = new Header[headerSize];
66+
int index = 0;
67+
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
68+
headers[index] = new BasicHeader(entry.getKey(), entry.getValue());
69+
index++;
70+
}
71+
request.setHeaders(headers);
72+
}
73+
74+
//设置request body
75+
StringEntity entity = new StringEntity(body);
76+
request.setEntity(entity);
77+
78+
//发起请求
79+
try {
80+
long start = System.currentTimeMillis();
81+
String response = httpClient.execute(request, responseHandler);
82+
long cost = System.currentTimeMillis() - start;
83+
log.info(String.format("[httpclient]["+key+"][cost] url[%s], postMethod cost time:%dms", url, cost));
84+
return response;
85+
} catch (ConnectionPoolTimeoutException e) {
86+
log.warn("[httpcient]["+key+"][timeout] connection pool timeout, url[" + url + "], msg[" + e.getMessage() + "].");
87+
throw e;
88+
} catch (SocketTimeoutException e) {
89+
log.warn("[httpcient]["+key+"][timeout] socket timeout, url[" + url + "], msg[" + e.getMessage() + "].");
90+
throw e;
91+
} catch (IOException e) {
92+
log.error(String.format("[httpclient]["+key+"][error] url[%s], msg = [%s].", url, e.getMessage()), e);
93+
throw e;
94+
}
95+
}
96+
97+
/**
98+
* get请求
99+
* 发送get请求,请求的url会根据url参数和params参数共同决定
100+
* 例如url参数="www.xxx.com",params参数="uid=1&timestamp=1510557964",
101+
* 则最终的请求url="www.xxx.com?uid=1&timestamp=1510557964"
102+
*
103+
* @param url 请求url
104+
* @param headerMap http header数据,key为header名,value为header值
105+
* @param params 请求参数
106+
* @return 响应数据
107+
* @throws IOException 请求过程中发生异常
108+
*/
109+
public String doGet(String url, Map<String, String> headerMap, String params) throws IOException {
110+
log.info("[httpclient]["+key+"] to get, url = [" + url + "], headerMap = [" + headerMap + "], params = [" + params + "].");
111+
//创建请求实例
112+
HttpGet request = new HttpGet(url + (params != null && params.length() > 0 ? "?" + params : ""));
113+
114+
if (headerMap != null && headerMap.size() > 0) {
115+
//设置Headers
116+
int headerSize = headerMap.size();
117+
Header[] headers = new Header[headerSize];
118+
int index = 0;
119+
for (Map.Entry<String, String> entry : headerMap.entrySet()) {
120+
headers[index] = new BasicHeader(entry.getKey(), entry.getValue());
121+
index++;
122+
}
123+
request.setHeaders(headers);
124+
}
125+
126+
//发起请求
127+
try {
128+
long start = System.currentTimeMillis();
129+
String response = httpClient.execute(request, responseHandler);
130+
long cost = System.currentTimeMillis() - start;
131+
log.info(String.format("[httpclient]["+key+"][cost] url[%s], postMethod cost time:%dms", url, cost));
132+
return response;
133+
} catch (ConnectionPoolTimeoutException e) {
134+
log.warn("[httpcient]["+key+"][timeout] connection pool timeout, url[" + url + "], msg[" + e.getMessage() + "].");
135+
throw e;
136+
} catch (SocketTimeoutException e) {
137+
log.warn("[httpcient]["+key+"][timeout] socket timeout, url[" + url + "], msg[" + e.getMessage() + "].");
138+
throw e;
139+
} catch (IOException e) {
140+
log.error(String.format("[httpclient]["+key+"][error] url[%s], msg = [%s].", url, e.getMessage()), e);
141+
throw e;
142+
}
143+
}
144+
145+
//请求响应Handler
146+
private ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
147+
@Override
148+
public String handleResponse(
149+
final HttpResponse response) throws IOException {
150+
StatusLine statusLine = response.getStatusLine();
151+
HttpEntity entity = response.getEntity();
152+
log.info("[httpclient]["+key+"] response: statusLine[" + statusLine + "].");
153+
if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
154+
throw new HttpResponseException(
155+
statusLine.getStatusCode(),
156+
statusLine.getReasonPhrase());
157+
}
158+
if (entity == null) {
159+
throw new ClientProtocolException("Response contains no content.");
160+
}
161+
ContentType contentType = ContentType.getOrDefault(entity);
162+
Charset charset = contentType.getCharset();
163+
BufferedReader reader = new BufferedReader(charset == null ? new InputStreamReader(entity.getContent()) : new InputStreamReader(entity.getContent(), charset));
164+
StringBuilder sb = new StringBuilder();
165+
String line;
166+
while ((line = reader.readLine()) != null)
167+
sb.append(line).append("\n");
168+
return sb.length() > 0 ? sb.substring(0, sb.length() - 1) : null;
169+
}
170+
};
171+
172+
/**
173+
* 创建HttpClient的Builder实例
174+
*
175+
* @param connectionManager 管理此client的HttpClientManager
176+
* @param key 此client的标识
177+
* @return Builder实例
178+
*/
179+
public static Builder instance(HttpClientManager connectionManager, String key) {
180+
return new Builder(connectionManager, key);
181+
}
182+
183+
//HttpClient的构造器
184+
public static class Builder {
185+
//建立连接 超时时间
186+
private int connectTimeout = 150;
187+
//等待响应 超时时间
188+
private int socketTimeout = 150;
189+
//从connectManager获取连接 超时时间
190+
private int connectRequestTimeout = 150;
191+
192+
//重试次数
193+
private int retryCount = 0;
194+
//重试开关
195+
private boolean retryEnable = false;
196+
197+
private final HttpClientManager connectionManager;
198+
199+
private final String key;
200+
201+
public Builder(HttpClientManager connectionManager, String key) {
202+
this.connectionManager = connectionManager;
203+
this.key = key;
204+
}
205+
206+
public Builder connectTimeout(int timeout) {
207+
this.connectTimeout = timeout;
208+
return this;
209+
}
210+
211+
public Builder socketTimeout(int socketTimeout) {
212+
this.socketTimeout = socketTimeout;
213+
return this;
214+
}
215+
216+
public Builder connectRequestTimeout(int connectRequestTimeout) {
217+
this.connectRequestTimeout = connectRequestTimeout;
218+
return this;
219+
}
220+
221+
public Builder retryCount(int retryCount) {
222+
if (retryCount > 0) {
223+
this.retryEnable = true;
224+
this.retryCount = retryCount;
225+
}
226+
return this;
227+
}
228+
229+
public HttpClient build() {
230+
org.apache.http.client.HttpClient client = HttpClients
231+
.custom()
232+
.setConnectionManager(connectionManager.getConnectionManager())
233+
.setDefaultRequestConfig(
234+
RequestConfig
235+
.custom()
236+
.setConnectTimeout(this.connectTimeout)
237+
.setSocketTimeout(this.socketTimeout)
238+
.setConnectionRequestTimeout(this.connectRequestTimeout)
239+
.build()
240+
)
241+
.setRetryHandler(new DefaultHttpRequestRetryHandler(this.retryCount, this.retryEnable))
242+
.build();
243+
244+
return new HttpClient(client, key);
245+
}
246+
}
247+
}

java/HttpClientManager.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package utils.http;
2+
3+
import org.apache.commons.logging.Log;
4+
import org.apache.commons.logging.LogFactory;
5+
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
6+
7+
/**
8+
* HttpClient池的实体类
9+
* 是对Apache的org.apache.http.impl.conn.PoolingHttpClientConnectionManager类的封装
10+
*
11+
* Created by littlelory on 02/11/2017.
12+
*/
13+
public class HttpClientManager {
14+
private static final Log log = LogFactory.getLog(HttpClientManager.class);
15+
16+
private final PoolingHttpClientConnectionManager connectionManager;
17+
18+
private static HttpClientManager instance;
19+
20+
private HttpClientManager(PoolingHttpClientConnectionManager manager) {
21+
this.connectionManager = manager;
22+
}
23+
24+
/**
25+
* 初始化
26+
*
27+
* @param maxTotal 此manager下所有Router的最大同时连接数
28+
* @param maxPerRount 每个Route的同时最大连接数
29+
*/
30+
public static void init(int maxTotal, int maxPerRount) {
31+
log.info("[http manager][init] maxTotal = ["+maxTotal+"], maxPerRount = ["+maxPerRount+"].");
32+
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
33+
// MAX_TOTAL_CONNECT = maxTotal;
34+
// MAX_PER_ROUTE_COUNT = maxPerRount;
35+
poolingHttpClientConnectionManager.setMaxTotal(maxTotal);
36+
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(maxPerRount);
37+
38+
// HttpClientManager manager = new HttpClientManager(poolingHttpClientConnectionManager);
39+
instance = new HttpClientManager(poolingHttpClientConnectionManager);
40+
log.info("[http manager][init] init success.");
41+
}
42+
43+
//获取HttpClientManager的实例
44+
public static HttpClientManager instance() {
45+
return instance;
46+
}
47+
48+
//获取封装的PoolingHttpClientConnectionManager实例
49+
PoolingHttpClientConnectionManager getConnectionManager() {
50+
return connectionManager;
51+
}
52+
}

java/HttpClientTest.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package utils.http;
2+
3+
import org.junit.Test;
4+
5+
import java.io.IOException;
6+
import java.util.HashMap;
7+
import java.util.Map;
8+
9+
public class HttpClientTest {
10+
private Map<String, String> headers = new HashMap<String, String>() {{
11+
put("accept", "*/*");
12+
put("connection", "Keep-Alive");
13+
put("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
14+
put("Accept-Charset", "utf-8");
15+
put("contentType", "utf-8");
16+
put("Content-Type", "application/x-www-form-urlencoded");
17+
}};
18+
19+
private HttpClient httpClient;
20+
21+
public void init() {
22+
//初始化HttpClientManager
23+
HttpClientManager.init(400, 200);
24+
//生成HttpClient实例
25+
httpClient = HttpClient.instance(HttpClientManager.instance(), "test")
26+
.connectRequestTimeout(1000)
27+
.connectTimeout(1000)
28+
.socketTimeout(5000)
29+
.build();
30+
}
31+
32+
@Test
33+
public void test() throws IOException {
34+
init();
35+
36+
String response = httpClient.doGet("http://www.baidu.com", headers, "uid=1&timestamp=1510557964");
37+
38+
System.out.println(response);
39+
}
40+
}

0 commit comments

Comments
 (0)