Http——HttpURLConnection詳解


 

HttpURLConnection簡介

在JDK的 java.net 包中已經提供了訪問HTTP協議的基本功能的類:HttpURLConnection

HttpURLConnection是Java的標准類,它繼承自URLConnection,可用於向指定網站發送GET請求、POST請求。

它在URLConnection的基礎上提供了如下便捷的方法:

int getResponseCode(); // 獲取服務器的響應代碼。
String getResponseMessage(); // 獲取服務器的響應消息。
String getResponseMethod(); // 獲取發送請求的方法。
void setRequestMethod(String method); // 設置發送請求的方法。

 

HttpURLConnection使用

  • 使用GET方式訪問HTTP
package com.qf.demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * GET請求示例*/
public class GetDemo {

    public static void main(String[] args) {
        try {
            // 1. 得到訪問地址的URL
            URL url = new URL("http://localhost:8080/Servlet/do_login.do?username=test&password=123456");
            // 2. 得到網絡訪問對象java.net.HttpURLConnection
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            /* 3. 設置請求參數(過期時間,輸入、輸出流、訪問方式),以流的形式進行連接 */
            // 設置是否向HttpURLConnection輸出
            connection.setDoOutput(false);
            // 設置是否從HttpUrlConnection讀入
            connection.setDoInput(true);
            // 設置請求方式
            connection.setRequestMethod("GET");
            // 設置是否使用緩存
            connection.setUseCaches(true);
            // 設置此 HttpURLConnection 實例是否應該自動執行 HTTP 重定向
            connection.setInstanceFollowRedirects(true);
            // 設置超時時間
            connection.setConnectTimeout(3000);
            // 連接
            connection.connect();
            // 4. 得到響應狀態碼的返回值 responseCode
            int code = connection.getResponseCode();
            // 5. 如果返回值正常,數據在網絡中是以流的形式得到服務端返回的數據
            String msg = "";
            if (code == 200) { // 正常響應
                // 從流中讀取響應信息
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line = null;
                while ((line = reader.readLine()) != null) { // 循環從流中讀取
                    msg += line + "\n";
                }
                reader.close(); // 關閉流
            }
            // 6. 斷開連接,釋放資源
            connection.disconnect();

            // 顯示響應結果
            System.out.println(msg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 使用POST方式訪問HTTP
package com.qf.demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * POST請求示例*/
public class PostDemo {

    public static void main(String[] args) {
        try {
            // 1. 獲取訪問地址URL
            URL url = new URL("http://localhost:8080/Servlet/do_login.do");
            // 2. 創建HttpURLConnection對象
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            /* 3. 設置請求參數等 */
            // 請求方式
            connection.setRequestMethod("POST");
            // 設置連接超時時間
            connection.setConnectTimeout(3000);
       // 設置是否向 HttpUrlConnection 輸出,對於post請求,參數要放在 http 正文內,因此需要設為true,默認為false。 connection.setDoOutput(true); // 設置是否從 HttpUrlConnection讀入,默認為true connection.setDoInput(true); // 設置是否使用緩存 connection.setUseCaches(false); // 設置此 HttpURLConnection 實例是否應該自動執行 HTTP 重定向 connection.setInstanceFollowRedirects(true); // 設置使用標准編碼格式編碼參數的名-值對 connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
       // 添加 HTTP HEAD 中的一些參數。
       // JDK8中,HttpURLConnection默認開啟Keep-Alive        // connection.setRequestProperty("Connection", "Keep-Alive");
// 連接 connection.connect(); /* 4. 處理輸入輸出 */ // 寫入參數到請求中 String params = "username=test&password=123456"; OutputStream out = connection.getOutputStream(); out.write(params.getBytes()); out.flush(); out.close(); // 從連接中讀取響應信息 String msg = ""; int code = connection.getResponseCode(); if (code == 200) { BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = reader.readLine()) != null) { msg += line + "\n"; } reader.close(); } // 5. 斷開連接 connection.disconnect(); // 處理結果 System.out.println(msg); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
  • Servlet服務端開發

 

HttpURLConnection說明

  • HttpURLConnection對象不能直接構造,需要通過URL類中的openConnection()方法來獲得。
  • 對HttpURLConnection對象的配置都需要在connect()方法執行之前完成,因為connect()會根據HttpURLConnection對象的配置值生成HTTP頭部信息。
  • HttpURLConnectionconnect()函數,實際上只是建立了一個與服務器的TCP連接,並沒有實際發送HTTP請求。HTTP請求實際上直到我們獲取服務器響應數據(如調用getInputStream()、getResponseCode()等方法)時才正式發送出去
  • HttpURLConnection是基於HTTP協議的,其底層通過socket通信實現。如果不設置超時(timeout),在網絡異常的情況下,可能會導致程序僵死而不繼續往下執行
  • HTTP正文的內容是通過OutputStream流寫入的, 向流中寫入的數據不會立即發送到網絡,而是存在於內存緩沖區中,待流關閉時,根據寫入的內容生成HTTP正文
  • 調用getInputStream()方法時,返回一個輸入流,用於從中讀取服務器對於HTTP請求的返回信息。
  • 我們可以使用HttpURLConnection.connect()方法手動的發送一個HTTP請求,但是如果要獲取HTTP響應的時候,請求就會自動的發起,比如我們使用HttpURLConnection.getInputStream()方法的時候,所以完全沒有必要調用connect()方法。

 

HttpURLConnection長連接(Keep-Alive)

JDK8自帶的HttpURLConnection,默認啟用keepAlive,支持HTTP / 1.1和HTTP / 1.0持久連接,

使用后的HttpURLConnection會放入緩存中供以后的同host:port的請求重用,底層的socketkeepAlive超時之前不會關閉。

HttpURLConnection受以下system properties控制:

  • http.keepAlive=<boolean>(默認值:true),是否啟用keepAlive,如果設置為false,則HttpURLConnection不會緩存,使用完后會關閉socket連接。
  • http.maxConnections=<int>(默認值:5),每個目標host緩存socket連接的最大數。

說明:

  1. 如果在HttpURLConnectionheader中加入Connection: close,則此連接不會啟用keepAlive
  2. 想要啟用keepAlive,程序請求完畢后,必須調用HttpURLConnection.getInputStream().close()(表示歸還長連接給緩存,以供下次同host:port的請求重用底層socket連接),而不能調用HttpURLConnection.disconnect()(表示關閉底層socket連接,不會啟用keepAlive
  3. keepAliveTimeout首先從http response header中獲取,如果沒有取到,則默認為5秒,sun.net.www.http.KeepAliveCache.java中有一個線程,每5秒執行一次,檢查緩存的連接的空閑時間是否超過keepAliveTimeout,如果超過則關閉連接。從KeepAliveCache中獲取緩存的連接時也會檢查獲取到的連接的空閑時間是否超過keepAliveTimeout,如果超過則關閉連接,並且獲取下一個連接,再執行以上檢查,直達獲取到空閑時間在keepAliveTimeout以內的緩存連接為此。

 

HttpURLConnection關閉

本身要 HttpURLConnection 是很簡單的,調用 connection.disconnect() 就可以了。

這里是想說明一下,是否需要關閉,應該根據實際需要來:

  • HttpURLConnection 是 "Connection: close " 模式,那么關閉 inputStream 后就會自動斷開連接。
  • HttpURLConnection 是 "Connection: Keep-Alive" 模式,那么關閉 inputStream 后,並不會斷開底層的 Socket 連接。這樣的好處,是當需要連接到同一服務器地址時,可以復用該 Socket。這時如果要求斷開連接,就可以調用 connection.disconnect() 了。

當然,HttpURLConnection 連接到底是不是 Keep-Alive 模式,除了 HttpURLConnection 請求設置為 Keep-Alive 外 (http 1.0中默認是關閉的,http 1.1中默認啟用Keep-Alive),也需要服務器支持 Keep-Alive,才可以真正建立 Keep-Alive 連接

 

與HttpClient的區別 

在一般情況下,如果只是需要向Web站點的某個簡單頁面提交請求並獲取服務器響應,HttpURLConnection完全可以勝任。但在絕大部分情況下,

Web站點的網頁可能沒這么簡單,這些頁面並不是通過一個簡單的URL就可訪問的,可能需要用戶登錄而且具有相應的權限才可訪問該頁面。

在這種情況下,就需要涉及Session、Cookie的處理了,如果打算使用HttpURLConnection來處理這些細節,當然也是可能實現的,只是處理起來難度就大了。

為了更好地處理向Web站點請求,包括處理Session、Cookie等細節問題,Apache開源組織提供了一個HttpClient項目,看它的名稱就知道,

它是一個簡單的HTTP客戶端(並不是瀏覽器),可以用於發送HTTP請求,接收HTTP響應。但不會緩存服務器的響應,

不能執行HTML頁面中嵌入的Javascript代碼;也不會對頁面內容進行任何解析、處理。

簡單來說,HttpClient就是一個增強版的HttpURLConnection,HttpURLConnection可以做的事情HttpClient全部可以做

HttpURLConnection沒有提供的有些功能,HttpClient也提供了,但它只是關注於如何發送請求、接收響應,以及管理HTTP連接。

 
 
參考:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM