在項目開發中,後端服務之間相互調用內部接口是常見場景。Java 標準庫提供的 HttpURLConnection 類無需引入第三方依賴,即可實現 HTTP 客戶端功能。本文通過完整代碼示例,詳細講解如何使用 HttpURLConnection 發送 GET 和 POST 請求,模擬瀏覽器行為,適用於接口調用、爬蟲、第三方支付回調等場景。
以下工具類封裝了 GET 與 POST 兩種請求方式,包含連接設置、參數編碼、流處理、異常捕獲等關鍵步驟。
package com.example.httpclient;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
public class HttpURLConnectionClient {
// 測試用目標接口(請替換為實際地址)
private static final String GET_URL = "https://example.com/api/user?storeId=32";
private static final String POST_URL = "https://example.com/api/user";
/**
* 發送 GET 請求
*/
public static String sendGet() {
StringBuilder response = new StringBuilder();
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(GET_URL);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.connect();
// 讀取響應流
reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
} catch (Exception e) {
e.printStackTrace();
return "請求失敗: " + e.getMessage();
} finally {
closeQuietly(reader);
if (connection != null) connection.disconnect();
}
return response.toString();
}
/**
* 發送 POST 請求(表單形式 application/x-www-form-urlencoded)
*
* @param storeId 業務參數
* @return 響應字符串
*/
public static String sendPost(String storeId) {
StringBuilder response = new StringBuilder();
HttpURLConnection connection = null;
DataOutputStream outputStream = null;
BufferedReader reader = null;
try {
URL url = new URL(POST_URL);
connection = (HttpURLConnection) url.openConnection();
// POST 必須設置的屬性
connection.setRequestMethod("POST");
connection.setDoOutput(true); // 允許輸出流寫入參數
connection.setDoInput(true); // 允許輸入流讀取響應
connection.setUseCaches(false); // 不使用緩存
connection.setInstanceFollowRedirects(true); // 自動跟隨重定向
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.connect();
// 寫入請求體參數
String params = "storeId=" + URLEncoder.encode(storeId, StandardCharsets.UTF_8.name());
outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(params);
outputStream.flush(); // 關鍵:刷新確保數據發送
// 讀取響應碼與響應體
int responseCode = connection.getResponseCode();
System.out.println("HTTP 響應碼: " + responseCode);
reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
} catch (Exception e) {
e.printStackTrace();
return "請求異常: " + e.getMessage();
} finally {
closeQuietly(outputStream);
closeQuietly(reader);
if (connection != null) connection.disconnect();
}
return response.toString();
}
/** 靜默關閉流,避免 finally 中再次拋異常 */
private static void closeQuietly(Closeable closeable) {
if (closeable != null) {
try { closeable.close(); } catch (IOException ignored) {}
}
}
// 測試入口
public static void main(String[] args) {
System.out.println("=== GET 請求結果 ===");
System.out.println(sendGet());
System.out.println("\n=== POST 請求結果 ===");
System.out.println(sendPost("32"));
}
}
url.openConnection() 返回 URLConnection,需強轉為 HttpURLConnection 以使用 HTTP 專用方法。setDoOutput(true),參數直接拼接在 URL 後。setDoOutput(true)、setDoInput(true)、setRequestMethod("POST")、setUseCaches(false),並設置 Content-Type 請求頭。URLEncoder.encode(param, "UTF-8") 對參數值進行編碼,防止中文亂碼或特殊字符截斷。connection.getOutputStream() 獲取輸出流,寫入參數字節,最後 必須 flush() 將緩衝區數據推送到網絡。connection.getInputStream() 時才會真正發起請求(連接建立、發送頭部與體)。BufferedReader 按行讀取響應體,拼接為完整字符串。| 問題 | 原因 | 解決方案 |
|---|---|---|
| 中文參數亂碼 | 未編碼或編碼不一致 | 統一使用 URLEncoder.encode(value, StandardCharsets.UTF_8),且服務端同樣用 UTF-8 解碼 |
| POST 請求服務端收不到參數 | 未設置 Content-Type 或未 flush | 設置 application/x-www-form-urlencoded,寫入後調用 flush() |
| 連接超時無異常拋出 | 未設置超時時間 | 必須調用 setConnectTimeout 和 setReadTimeout(毫秒) |
| 長連接導致後續請求卡死 | 未調用 disconnect() 或流未關閉 | finally 中確保 connection.disconnect(),並關閉所有流 |
| HTTPS 請求報 SSLHandshakeException | 默認不信任自簽名證書 | 需配置信任管理器或導入證書至 cacerts,生產環境建議使用成熟 HTTP 客戶端(OkHttp、HttpClient) |
Content-Type 改為 application/json;charset=UTF-8,寫入 JSON 字符串字節。Content-Type: multipart/form-data; boundary=xxx,按 RFC 2046 格式構建請求體(建議改用 Apache HttpClient 或 OkHttp)。HttpURLConnection 底層有緩存(http.keepAlive),高併發場景建議引入 Apache HttpClient 或 OkHttp,支持連接池、攔截器、異步請求等高級特性。HttpURLConnection 是 Java 原生 HTTP 客戶端,零依賴、輕量級,適合簡單的同步調用場景。掌握其正確使用姿勢(設置屬性順序、流處理、異常與資源管理)是 Java 後端開發的基本功。對於複雜的生產環境接口調用,強烈推薦使用 OkHttp 或 Apache HttpClient 5.x,功能更豐富、穩健性更高。