前言
- 使用Apache的HttpClient庫,添加Apache HttpClient的依賴。
- 工具類的封裝。通常,工具類需要處理GET、POST請求,可能還有其他方法如PUT、DELETE。需要設計一個工具類,提供靜態方法,可以發送請求,并處理響應。同時要考慮連接超時、讀取超時的設置,以及請求頭的配置,比如Content-Type、User-Agent等
- 然后,需要處理請求參數的封裝。對于GET請求,參數通常是查詢字符串;對于POST,可能需要表單參數或者JSON body。因此,工具類可能需要支持不同的參數類型,比如使用Map<String, String>來傳遞表單參數,或者直接傳入一個JSON字符串作為請求體。
- 異常處理也是關鍵。網絡請求可能會拋出IOException等異常,工具類需要捕獲這些異常,并可能轉換成自定義異常,或者返回null,或者記錄日志,具體取決于設計選擇。需要靈活處理錯誤,所以可能需要將異常拋出讓調用者處理,或者在工具類內部處理并返回錯誤信息。
- 另外,響應處理方面,需要將HttpEntity轉換為字符串,并正確關閉連接,確保資源釋放。使用EntityUtils.toString時要注意字符編碼,通常使用UTF-8。同時,需要關閉HttpResponse和HttpClient,或者使用try-with-resources來自動管理資源,但Apache HttpClient 4.x版本的response關閉可能需要注意,需要確保正確關閉流。
注意事項
-
工具類可能包含sendGet和sendPost方法。例如,sendGet接收URL和參數Map,構造帶查詢參數的URL;sendPost接收URL和可能的表單參數或JSON body,并設置合適的Content-Type。此外,可能需要設置請求頭,比如設置JSON的Content-Type為application/json。
-
工具類的設計要盡量簡潔,可配置。比如,可以允許自定義連接超時時間、讀取超時時間,或者設置默認的請求頭。可能使用HttpClient的配置,比如RequestConfig來設置超時參數。
-
可能的陷阱包括:未正確處理參數編碼,比如在GET請求中,參數需要進行URL編碼;在POST發送表單時,需要將參數轉換為UrlEncodedFormEntity;發送JSON時,要使用StringEntity,并設置Content-Type為application/json。
-
需要注意線程安全,HttpClient通常建議重用實例,所以工具類中可能使用靜態的CloseableHttpClient實例,并通過靜態代碼塊初始化,確保線程安全。但需確認是否每次請求需要新的實例,或者可以共享。根據Apache HttpClient文檔,建議重復使用同一個實例,因為它是線程安全的,并且管理連接池更高效。所以工具類中可以創建一個單例的HttpClient實例。
-
另外,工具類可能需要處理不同的Content-Type,比如POST發送JSON時,需要設置對應的頭信息,并處理不同的數據體。因此,sendPost可能需要參數來指定發送的數據類型,或者通過方法重載來處理不同情況。
-
例如,提供sendPostForm用于發送表單,sendPostJson用于發送JSON。或者,在方法中傳遞一個contentType參數,并根據類型構造不同的HttpEntity。
-
或者,更靈活的方式是讓調用者傳入一個HttpEntity對象,這樣工具類更通用,但使用起來可能不夠方便。所以需要在易用性和靈活性之間權衡。
-
這里工具類可以提供兩個方法:一個處理表單參數(Map類型),另一個處理JSON字符串。
-
整體思路
-
引入Apache HttpClient依賴。
-
創建HttpClientUtil類,封裝創建HttpClient實例的方法,配置超時等參數。
-
實現sendGet方法,處理參數拼接和編碼。
-
實現sendPost方法,處理表單或JSON數據的提交。
-
處理響應,將結果轉換為字符串。
-
異常處理,關閉資源。
-
提供使用示例。
代碼示例
Maven依賴
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency>
HttpClientUtil
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
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.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;public class HttpClientUtil {// 超時配置(單位:毫秒)private static final int CONNECT_TIMEOUT = 5000;private static final int SOCKET_TIMEOUT = 5000;// 創建可復用的HttpClient實例private static final CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build()).build();/*** 發送GET請求* @param url 請求地址* @param params 請求參數* @return 響應內容*/public static String sendGet(String url, Map<String, String> params) {HttpGet httpGet = new HttpGet(buildUri(url, params));try (CloseableHttpResponse response = httpClient.execute(httpGet)) {return handleResponse(response);} catch (IOException e) {throw new RuntimeException("GET請求失敗", e);}}/*** 發送POST表單請求(application/x-www-form-urlencoded)* @param url 請求地址* @param formData 表單數據* @return 響應內容*/public static String sendPostForm(String url, Map<String, String> formData) {HttpPost httpPost = new HttpPost(url);List<NameValuePair> params = new ArrayList<>();formData.forEach((k, v) -> params.add(new BasicNameValuePair(k, v)));httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));return executePost(httpPost);}/*** 發送POST JSON請求(application/json)* @param url 請求地址* @param json JSON字符串* @return 響應內容*/public static String sendPostJson(String url, String json) {HttpPost httpPost = new HttpPost(url);StringEntity entity = new StringEntity(json, "UTF-8");entity.setContentType("application/json");httpPost.setEntity(entity);return executePost(httpPost);}private static String executePost(HttpPost httpPost) {try (CloseableHttpResponse response = httpClient.execute(httpPost)) {return handleResponse(response);} catch (IOException e) {throw new RuntimeException("POST請求失敗", e);}}private static URI buildUri(String url, Map<String, String> params) {try {URIBuilder uriBuilder = new URIBuilder(url);if (params != null) {params.forEach(uriBuilder::addParameter);}return uriBuilder.build();} catch (URISyntaxException e) {throw new IllegalArgumentException("URL格式錯誤", e);}}private static String handleResponse(CloseableHttpResponse response) throws IOException {int statusCode = response.getStatusLine().getStatusCode();if (statusCode != 200) {throw new RuntimeException("HTTP響應異常,狀態碼:" + statusCode);}HttpEntity entity = response.getEntity();return entity != null ? EntityUtils.toString(entity, "UTF-8") : null;}
}
使用示例
import java.util.HashMap;
import java.util.Map;public class Example {public static void main(String[] args) {// GET請求示例String getUrl = "https://api.example.com/data";Map<String, String> params = new HashMap<>();params.put("key1", "value1");params.put("key2", "value2");String getResponse = HttpClientUtil.sendGet(getUrl, params);System.out.println("GET響應內容:" + getResponse);// POST表單示例String postFormUrl = "https://api.example.com/submit";Map<String, String> formData = new HashMap<>();formData.put("username", "testuser");formData.put("password", "testpass");String postFormResponse = HttpClientUtil.sendPostForm(postFormUrl, formData);System.out.println("POST表單響應:" + postFormResponse);// POST JSON示例String postJsonUrl = "https://api.example.com/submit-json";String jsonPayload = "{\"name\":\"John\", \"age\":30}";String postJsonResponse = HttpClientUtil.sendPostJson(postJsonUrl, jsonPayload);System.out.println("POST JSON響應:" + postJsonResponse);}
}
總結
工具類特點:
- 線程安全: 使用單個共享的HttpClient實例,復用連接池資源
- 超時配置: 統一設置5秒連接/讀取超時
- 編碼處理: 統一使用UTF-8編碼
- 異常處理: 將檢查異常轉換為運行時異常,簡化調用
- 支持多種請求:
- GET請求(帶查詢參數)
- POST表單(application/x-www-form-urlencoded)
- POST JSON(application/json)
- 響應處理: 自動驗證狀態碼并轉換響應內容
注意事項:
- 根據實際情況調整超時時間配置
- 生產環境建議添加日志記錄
- 需要處理其他狀態碼(如3xx重定向)時可擴展handleResponse方法
- 如需添加自定義請求頭,可擴展方法參數
- 注意及時釋放資源,使用try-with-resources自動關閉響應
可根據實際需求進一步擴展支持:
- 文件上傳
- HTTPS配置
- 代理設置
- 請求重試機制
- 更完善的異常處理等