#IT明星不是夢#【從0開始Web開發實戰】SpringBoot集成HttpClient,開發進階

目錄:

1. SpringBoot集成HttpClient

2. 封裝服務HttpService.java,處理請求參數

3. 封裝ResponseHandler<T>處理返回結果

4. 單元測試

5. 功能調用

6. 常見問題和解決方法


HttpClient是Apache Jakarta Common下的子項目,是一個高效的、功能豐富的HTTP客戶端編程工具包,以編程的方式通過API傳輸和接收HTTP消息。主要功能:

支持HTTP方法:GET, POST, PUT, DELETE, HEAD, OPTIONS等

支持HTTPS協議

支持多線程應用和連接管理,可設置最大連接數

支持KeepAlive持久連接

支持自定義Cookie策略

支持代理服務器:ngnix等

支持自動跳轉

......


本文分享SpringBoot集成和配置HttpClient的方法,並封裝HttpService調用請求和ResponseHandler處理返回結果,添加REST接口,演示項目中實際應用。


代碼文件

功能要點

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請求並返回結果。


代碼下載:https://github.com/jextop/StarterApi/


一,SpringBoot集成HttpClient

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連接屬性配置,聲明RequestConfigHttpClientConnectionManager,並且創建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();
    }

}


二,封裝服務HttpService.java,處理請求參數,調用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());
        }
    }
}

HttpService中使用RespStr處理HttpResponse,返回字符串。


三,封裝ResponseHandler<T>處理返回結果

ResponseHandler<T>是httpclient包內提供的接口,實現函數handleResponse()處理HTTP返回結果,封裝處理邏輯。

package org.apache.http.client;

import java.io.IOException;
import org.apache.http.HttpResponse;

public interface ResponseHandler<T> {
    T handleResponse(HttpResponse var1) throws ClientProtocolException, IOException;
}

封裝的4個HTTP返回結果處理類,簡化邏輯,提高開發效率。

image.png

代碼文件

HTTP返回結果類型

RespStr.java

返回字符串

RespJsonObj.java

返回JSONObject

RespJsonArr.java

返回JSONArray

RespFile.java

返回二進制文件


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;
    }
}


四,單元測試,調用HttpService發送請求和處理返回結果

image.png 

五,功能調用

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);
    }};
}

3. REST接口調用HttpSevice示例

image.png 

六,常見問題和解決方法

HTTP返回結果亂碼,設置UTF-8仍然不能解決?

原因:處理HTTP請求返回結果時,出現亂碼是因爲設置Charset編碼格式不正確,通常設置UTF-8可以解決大部分情況,但並不是所有HTTP服務器都一定使用UTF-8格式。

解決:正確的方法是獲取內容編碼時的格式:

- 調用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);
    }
}

ResponseHandler<T>httpclient包內提供的接口,實現函數handleResponse()處理HTTP返回結果。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章