HttpClient是Apache Jakarta Common下的子項目,是一個高效的、功能豐富的HTTP客戶端編程工具包,以編程的方式經過API傳輸和接收HTTP消息。主要功能:
html
l 支持HTTP方法:GET, POST, PUT, DELETE, HEAD, OPTIONS等java
l 支持HTTPS協議git
l 支持多線程應用和鏈接管理,可設置最大鏈接數github
l 支持KeepAlive持久鏈接apache
l 支持自定義Cookie策略編程
l 支持代理服務器:ngnix等json
l 支持自動跳轉服務器
l ......多線程
本文分享Spring集成和配置HttpClient的方法,並封裝HttpService,經過添加一個REST接口,演示項目中的實際應用。app
代碼文件 |
功能要點 |
|
SpringBoot集成HttpClient |
pom.xml |
引入HttpClient依賴:org.apache.httpcomponents包裏的httpclient, httpcore, httpmime |
application.yml |
配置HTTP鏈接屬性 |
|
HttpConfig.java |
配置Bean: HttpClient,以及RequestConfig和HttpClientConnectionManager |
|
封裝服務HttpService |
HttpService.java |
處理HTTP請求參數,調用HttpClient發送請求 |
處理返回結果ResponseHandler<T> |
RespStr.java RespJsonObj.java RespJsonArr.java RespFile.java |
對HttpResponse進行處理,讀取HttpEntity並對返回內容進行轉換 |
單元測試 |
HttpServiceTest.java |
測試HttpService發送請求和處理返回結果 |
功能調用 |
CheckController.java |
增長REST接口/chk/http,發送HTTP請求並返回結果。 |
l 代碼
Github下載:https://github.com/jextop/StarterApi/
l SpringBoot集成Client
1. 在pom.xml中添加httpclient, httpcore, httpmime依賴。
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.4</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5</version>
</dependency>
2. 在application.yml中配置HTTP鏈接屬性,指定最大鏈接數、超時時間等:
http:
maxTotal: 100
maxPerRoute: 20
socketTimeout: 5000
connectTimeout: 5000
requestTimeout: 5000
3. 在HttpConfig.java中配置Bean,讀取HTTP鏈接屬性配置,聲明RequestConfig和HttpClientConnectionManager,而且建立HttpClient實例:
@Configuration
@ConfigurationProperties("http")
public class HttpConfig {
private Integer maxTotal;
private Integer maxPerRoute;
private Integer socketTimeout;
private Integer connectTimeout;
private Integer requestTimeout;
@Bean
public HttpClientConnectionManager httpClientConnectionManager() {
PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager();
connMgr.setMaxTotal(maxTotal);
connMgr.setDefaultMaxPerRoute(maxPerRoute);
return connMgr;
}
@Bean
public RequestConfig requestConfig() {
return RequestConfig.custom()
.setSocketTimeout(socketTimeout)
.setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(requestTimeout)
.build();
}
@Bean
public HttpClient httpClient(HttpClientConnectionManager manager, RequestConfig config) {
return HttpClientBuilder.create()
.setConnectionManager(manager)
.setDefaultRequestConfig(config)
.build();
}
}
l 封裝服務HttpService.java,處理HTTP請求參數,調用HttpClient發送請求。
@Service
public class HttpService {
@Autowired
private HttpClient httpClient;
public <T> T sendRequest(HttpRequestBase httpRequest, ResponseHandler<T> handler) {
try {
return httpClient.execute(httpRequest, handler);
} catch (ClientProtocolException e) {
LogUtil.error("Error when sendRequest", e.getMessage());
} catch (IOException e) {
LogUtil.error("Error when sendRequest", e.getMessage());
}
return null;
}
public <T> T sendHttpGet(String url, ResponseHandler<T> handler) {
return sendRequest(new HttpGet(url), handler);
}
public String sendHttpGet(String url) {
return sendHttpGet(url, new RespStr());
}
public <T> T sendHttpGet(String url, Map<String, String> headers, ResponseHandler<T> handler) {
HttpGet httpGet = new HttpGet(url);
fillHeaders(httpGet, headers);
return sendRequest(httpGet, handler);
}
private static void fillHeaders(HttpRequestBase request, Map<String, String> headers) {
for (Map.Entry<String, String> header : headers.entrySet()) {
request.addHeader(header.getKey(), header.getValue());
}
}
}
l 處理返回結果,封裝ResponseHandler<T>
1. RespStr.java:讀取HttpResponse返回的內容,格式化爲String字符串
- 調用httpResponse.getEntiry()獲取返回結果
- 調用ContentType.get()獲取內容類型
- 調用ContentType.getCharset()獲取編碼格式
- 調用EntityUtils.toString()將返回結果格式化爲字符串
public class RespStr implements ResponseHandler<String> {
@Override
public String handleResponse(HttpResponse httpResponse) throws ClientProtocolException, IOException {
HttpEntity entity = httpResponse.getEntity();
ContentType contentType = ContentType.getOrDefault(entity);
Charset charset = contentType.getCharset();
return EntityUtils.toString(entity, charset);
}
}
2. RespJsonObj.java:在返回結果爲JSON對象時,轉換成JSONObject返回
public class RespJsonObj implements ResponseHandler<JSONObject> {
@Override
public JSONObject handleResponse(HttpResponse resp) throws ClientProtocolException, IOException {
HttpEntity entity = resp.getEntity();
ContentType contentType = ContentType.getOrDefault(entity);
Charset charset = contentType.getCharset();
String jsonStr = EntityUtils.toString(entity, charset);
// parse JSON object
return JsonUtil.parseObj(jsonStr);
}
}
3. RespJsonArr.java:將HTTP請求返回結果轉換成JSONArray返回
public class RespJsonArr implements ResponseHandler<JSONArray> {
@Override
public JSONArray handleResponse(HttpResponse resp) throws ClientProtocolException, IOException {
HttpEntity entity = resp.getEntity();
ContentType contentType = ContentType.getOrDefault(entity);
Charset charset = contentType.getCharset();
String jsonStr = EntityUtils.toString(entity, charset);
// parse JSON array
return JsonUtil.parseArr(jsonStr);
}
}
4. RespFile.java:在HTTP返回二進制文件時,從Entity中讀取二進制內容,並可從Header中獲取文件名稱。
public class RespFile implements ResponseHandler<byte[]> {
private static final String fileNameFlag = "attachment;fileName=";
private byte[] bytes;
private String fileName;
public byte[] getBytes() {
return bytes;
}
public String getFileName() {
return fileName;
}
@Override
public byte[] handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
// Header: Content-Disposition: attachment;fileName=abc.txt
Header header = response.getFirstHeader("Content-Disposition");
String headerValue = header.getValue();
if (headerValue.startsWith(fileNameFlag)) {
fileName = headerValue.substring(fileNameFlag.length(), headerValue.length());
}
HttpEntity entity = response.getEntity();
bytes = EntityUtils.toByteArray(entity);
return bytes;
}
}
l 單元測試,調用HttpService發送請求和處理返回結果
l 功能調用
1. 增長RestController:CheckController.java
2. 增長REST接口/chk/http,發送HTTP請求並返回結果。
@GetMapping(value = "/chk/http", produces = "application/json")
public Object http() {
String strCourse = httpService.sendHttpGet("https://edu.51cto.com/lecturer/13841865.html");
String[] courses = StrUtil.parse(strCourse, "[1-9]\\d*人學習");
return new HashMap<String, Object>() {{
put("chk", "http");
put("course", courses);
}};
}
l REST接口調用HttpSevice示例