首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 後端使用 HttpURLConnection 模擬瀏覽器請求(GET/POST)完整實戰

     編輯:Java 相關知識

引言

在項目開發中,後端服務之間相互調用內部接口是常見場景。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"));
    }
}

關鍵步驟解析

1. 連接建立與配置

  • url.openConnection() 返回 URLConnection,需強轉為 HttpURLConnection 以使用 HTTP 專用方法。
  • GET:默認不需設置 setDoOutput(true),參數直接拼接在 URL 後。
  • POST:必須設置 setDoOutput(true)、setDoInput(true)、setRequestMethod("POST")、setUseCaches(false),並設置 Content-Type 請求頭。

2. 參數編碼與寫入

  • 使用 URLEncoder.encode(param, "UTF-8") 對參數值進行編碼,防止中文亂碼或特殊字符截斷。
  • 通過 connection.getOutputStream() 獲取輸出流,寫入參數字節,最後 必須 flush() 將緩衝區數據推送到網絡。

3. 響應處理與資源釋放

  • 調用 connection.getInputStream() 時才會真正發起請求(連接建立、發送頭部與體)。
  • 使用 BufferedReader 按行讀取響應體,拼接為完整字符串。
  • finally 塊中依次關閉:輸出流 → 輸入流 → 斷開連接,防止連接洩漏導致客戶端耗盡端口。

常見坑點與最佳實踐

問題原因解決方案
中文參數亂碼未編碼或編碼不一致統一使用 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)

擴展建議

  • JSON 請求體:將 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,功能更豐富、穩健性更高。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved