URLConnection類,HttpURLConnection類的使用和總結

bingguang1993發表於2018-04-14

1.URLConnection類

1.1 URLConnection類概述

抽象類 URLConnection 是所有類的超類,它代表應用程式和 URL 之間的通訊連結。此類的例項可用於讀取和寫入此 URL 引用的資源。URLConnection 基於Http協議。通常,建立一個到 URL 的連線需要幾個步驟:

openConnection() connect()
對影響到遠端資源連線的引數進行操作。 與資源互動;查詢頭欄位和內容。

1. 通過在 URL 上呼叫 openConnection 方法建立連線物件。 
2. 處理設定引數和一般請求屬性。 
3. 使用 connect 方法建立到遠端物件的實際連線。 
4. 遠端物件變為可用。遠端物件的頭欄位和內容變為可訪問。


使用以下方法修改設定引數:

  • setAllowUserInteraction 設定此 URLConnection 的 allowUserInteraction 欄位的值
  • setDoInput 將此 URLConnection 的 doInput 欄位的值設定為指定的值。
  • setDoOutput 將此 URLConnection 的 doOutput 欄位的值設定為指定的值。
  • setIfModifiedSince 將此 URLConnection 的 ifModifiedSince 欄位的值設定為指定的值。
  • setUseCaches 將此 URLConnection 的 useCaches 欄位的值設定為指定的值
  • setConnectTimeout 設定一個指定的超時值(以毫秒為單位),該值將在開啟到此 URLConnection 引用的資源的通訊連結時使用。
  • setReadTimeout 將讀超時設定為指定的超時值,以毫秒為單位。

使用 setDefaultAllowUserInteraction 和 setDefaultUseCaches 可設定 AllowUserInteraction 和 UseCaches 引數的預設值。


使用以下方法修改一般請求屬性:

  • setRequestProperty 設定一般請求屬性。
  • addRequestProperty 新增由鍵值對指定的一般請求屬性。

上面每個 set 方法都有一個用於獲取引數值或一般請求屬性值的對應 get 方法。 
例如 
- getDoInput() 
- getIfModifiedSince()


在建立到遠端物件的連線後,以下方法用於訪問頭欄位和內容:

  • getContent 獲取此 URL 連線的內容。
  • getHeaderField 返回指定的頭欄位的值。
  • getInputStream 返回從此開啟的連線讀取的輸入流。
  • getOutputStream 返回寫入到此連線的輸出流。

某些頭欄位需要經常訪問。以下方法:

  • getContentEncoding 返回 content-encoding 頭欄位的值。
  • getContentLength 返回 content-length 頭欄位的值。
  • getContentType 返回 content-type 頭欄位的值。
  • getDate 返回 date 頭欄位的值。
  • getExpiration 返回 expires 頭欄位的值。
  • getLastModifed 返回 last-modified 頭欄位的值。

1.2 URLConnection類的使用

1.2.1 傳送GET請求示例程式碼

1.通過在 URL 上呼叫 openConnection 方法建立連線物件。 
2.處理設定引數和一般請求屬性。 
3.使用 connect 方法建立到遠端物件的實際連線。 
4.遠端物件變為可用。遠端物件的頭欄位和內容變為可訪問。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;

public class URLConnectionGet {

    public static void main(String[] args) {
        // TODO 自動生成的方法存根

        System.out.println(doGet("http://www.baidu.com",""));

    }

    public static String doGet(String geturl,String params) {
        String realUrl=geturl+"?"+params;

        try {
            //1.通過在 URL 上呼叫 openConnection 方法建立連線物件
            URL url=new URL(realUrl);
            URLConnection conn=url.openConnection();

            //2.處理設定引數和一般請求屬性
            //2.1設定引數
            //可以根據請求的需要設定引數 
            conn.setUseCaches(false);
            conn.setConnectTimeout(5000); //請求超時時間

            //2.2請求屬性 
            //設定通用的請求屬性 更多的頭欄位資訊可以查閱HTTP協議
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");

            //3.使用 connect 方法建立到遠端物件的實際連線。 
            conn.connect();

            //4.遠端物件變為可用。遠端物件的頭欄位和內容變為可訪問。 
            //4.1獲取響應的頭欄位
            Map<String, List<String>> headers=conn.getHeaderFields();
            System.out.println(headers); //輸出頭欄位

            //4.2獲取響應正文
            BufferedReader reader = null;
            StringBuffer resultBuffer = new StringBuffer();
            String tempLine = null;

            reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            while ((tempLine = reader.readLine()) != null) {
                resultBuffer.append(tempLine);
            }
            //System.out.println(resultBuffer);
            reader.close();
            return resultBuffer.toString();
        } catch (MalformedURLException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        } catch (IOException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        }
        finally {

        }
        return null;

    }
}

1.2.1 傳送POST請求示例程式碼

1.通過在 URL 上呼叫 openConnection 方法建立連線物件。 
2.處理設定引數和一般請求屬性,獲取URLconnection例項對應的輸出流來傳送資料。 
3.使用 connect 方法建立到遠端物件的實際連線。 
4.遠端物件變為可用。遠端物件的頭欄位和內容變為可訪問。 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;

public class URLConnectionPost {

    public static void main(String[] args) {
        // TODO 自動生成的方法存根

        System.out.println();

    }

    public static String doPost(String posturl,String params) {


        try {
            //1.通過在 URL 上呼叫 openConnection 方法建立連線物件
            URL url=new URL(posturl);
            URLConnection conn=url.openConnection();

            //2.處理設定引數和一般請求屬性
            //2.1設定引數
            //可以根據請求的需要設定引數 
            conn.setDoInput (true);  //預設為true 所以不設定也可以
            conn.setDoOutput(true);  //預設為false 傳送post請求必須設定setDoOutput(true)
            conn.setUseCaches(false); //是否可以使用快取 不使用快取
            conn.setConnectTimeout(5000);//請求超時時間

            //2.2請求屬性 
            //設定通用的請求屬性 訊息報頭 即設定頭欄位 更多的頭欄位資訊可以查閱HTTP協議
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");

            //2.3設定請求正文 即要提交的資料
            PrintWriter pw=new PrintWriter(new OutputStreamWriter(conn.getOutputStream()));
            pw.print(params);
            pw.flush();
            pw.close();

            //3.使用 connect 方法建立到遠端物件的實際連線。 
            conn.connect();

            //4.遠端物件變為可用。遠端物件的頭欄位和內容變為可訪問。 
            //4.1獲取響應的頭欄位
            Map<String, List<String>> headers=conn.getHeaderFields();
            System.out.println(headers); //輸出頭欄位

            //4.2獲取響應正文
            BufferedReader reader = null;
            StringBuffer resultBuffer = new StringBuffer();
            String tempLine = null;

            reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            while ((tempLine = reader.readLine()) != null) {
                resultBuffer.append(tempLine);
            }
            //System.out.println(resultBuffer);
            reader.close();
            return resultBuffer.toString();
        } catch (MalformedURLException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        } catch (IOException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        }
        finally {

        }
        return null;

    }
}
  •  

1.3 URLConnection類分析

1.3.1 URLConnection物件例項化

URL url = new URL("http://www.baidu.com/");
URLConnection conn = url.openConnection();

1.URL url = new URL("http://www.baidu.com/");
檢視URL的原始碼
public URL(String spec) throws MalformedURLException {
this(null, spec);
}
public URL(URL context, String spec) throws MalformedURLException {
this(context, spec, null);
}
public URL(URL context, String spec, URLStreamHandler handler)

檢視原始碼得知最終URL(String spec)會呼叫URL(URL context, String spec, URLStreamHandler handler)
此時此時context和handler為null。
在建構函式URL(URL context, String spec, URLStreamHandler handler)中
如果handler為空會呼叫 handler =getURLStreamHandler(protocol)的方法根據protocol協議初始化handler
handler為URLStreamHandler的子類例項

2.URLConnection conn = url.openConnection();

public URLConnection openConnection() throws java.io.IOException {
    return handler.openConnection(this);
}

handler.openConnection(this);返回的是URLConnection子類的例項。所以最好把URLConnection轉化
  •  

1.4 URLConnection總結

  1. URLConnection的connect()函式,實際上只是建立了一個與伺服器的tcp連線,並沒有實際傳送http請求。 
    無論是post還是get,http請求實際上直到HttpURLConnection的getInputStream()這個函式裡面才正式傳送出去。

  2. 在用POST方式傳送URL請求時,URL請求引數的設定順序是重中之重, 
    對connection物件的處理設定引數和一般請求屬性和寫入提交資料都必須要在connect()函式執行之前完成。對outputStream的寫提交資料操作,必須要在inputStream的讀操作之前。這些順序實際上是由http請求的格式決定的。

  3. http請求實際上由兩部分組成,一個是http頭,所有關於此次http請求的配置都在http頭裡面定義,一個是正文content。connect()函式會根據HttpURLConnection物件的配置值生成http頭部資訊,因此在呼叫connect函式之前,就必須把所有的配置準備好。

  4. 在http頭後面緊跟著的是http請求的正文,正文的內容是通過outputStream流寫入的, 
    實際上outputStream不是一個網路流,充其量是個字串流,往裡面寫入的東西不會立即傳送到網路,而是存在於記憶體緩衝區中,待outputStream流關閉時,根據輸入的內容生成http正文。至此,http請求的東西已經全部準備就緒。在getInputStream()函式呼叫的時候,就會把準備好的http請求正式傳送到伺服器了,然後返回一個輸入流,用於讀取伺服器對於此次http請求的返回資訊。由於http請求在getInputStream的時候已經傳送出去了(包括http頭和正文),因此在getInputStream()函式之後對connection物件進行設定(對http頭的資訊進行修改)或者寫入outputStream(對正文進行修改)都是沒有意義的了,執行這些操作會導致異常的發生。


2.HttpURLConnection類

2.1 HttpURLConnection類概述

支援 HTTP 特定功能的 URLConnection。每個 HttpURLConnection 例項都可用於生成單個請求,但是其他例項可以透明地共享連線到 HTTP 伺服器的基礎網路。請求後在 HttpURLConnection 的 InputStream 或 OutputStream 上呼叫 close() 方法可以釋放與此例項關聯的網路資源,但對共享的持久連線沒有任何影響。如果在呼叫 disconnect() 時持久連線空閒,則可能關閉基礎套接字。

URLConnection 是所有類的超類,它代表應用程式和 URL 之間的通訊連結。該類的例項可以用來對由 URL 引用的資源進行讀取和寫入操作。

  1. 通過在 URL 上呼叫 openConnection 方法創HttpURLConnection建連線物件。
  2. 處理設定引數和一般請求屬性。
  3. 使用 connect 方法建立到遠端物件的實際連線。
  4. 遠端物件變為可用。遠端物件的頭欄位和內容變為可訪問。

使用以下方法修改設定引數:

HttpURLConnection繼承自URLConnection,相比較URLConnection類多了以下方法。 
- setRequestMethod 設定 URL 請求的方法, GET POST HEAD OPTIONS PUT DELETE TRACE 以上方法之一是合法的,具體取決於協議的限制。 
- setFollowRedirects 設定此類是否應該自動執行 HTTP 重定向(響應程式碼為 3xx 的請求)。


使用以下方法修改一般請求屬性:

  • setRequestProperty 設定一般請求屬性。
  • addRequestProperty 新增由鍵值對指定的一般請求屬性。

在建立到遠端物件的連線後,以下方法用於訪問頭欄位和內容:

HttpURLConnection繼承自URLConnection,相比較URLConnection類多了以下方法。 
- getResponseCode 從 HTTP 響應訊息獲取狀態碼。 
- getResponseMessage 獲取與來自伺服器的響應程式碼一起返回的 HTTP 響應訊息(如果有)。

2.2 HttpURLConnection類使用

2.2.1 傳送GET請求示例程式碼

public static String doGet(String geturl,String params) {
        String realUrl=geturl+"?"+params;

        try {
            //1.通過在 URL 上呼叫 openConnection 方法建立連線物件
            URL url=new URL(realUrl);
            //此處的urlConnection物件實際上是根據URL的請求協議(此處是http)生成的URLConnection類的子類HttpURLConnection,
            //故此處最好將其轉化為HttpURLConnection型別的物件
            HttpURLConnection conn=(HttpURLConnection) url.openConnection();

            //2.處理設定引數和一般請求屬性
            //2.1設定引數
            //可以根據請求的需要設定引數 
            conn.setRequestMethod("GET"); //預設為GET 所以GET不設定也行
            conn.setUseCaches(false);
            conn.setConnectTimeout(5000); //請求超時時間

            //2.2請求屬性 
            //設定通用的請求屬性 更多的頭欄位資訊可以查閱HTTP協議
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");

            //3.使用 connect 方法建立到遠端物件的實際連線。 
            conn.connect();

            //4.遠端物件變為可用。遠端物件的頭欄位和內容變為可訪問。
            //4.1獲取HTTP 響應訊息獲取狀態碼
            if(conn.getResponseCode()==200)
            {
                //4.2獲取響應的頭欄位
                Map<String, List<String>> headers=conn.getHeaderFields();
                System.out.println(headers); //輸出頭欄位

                //4.3獲取響應正文
                BufferedReader reader = null;
                StringBuffer resultBuffer = new StringBuffer();
                String tempLine = null;

                reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                while ((tempLine = reader.readLine()) != null) {
                    resultBuffer.append(tempLine);
                }
                //System.out.println(resultBuffer);
                reader.close();
                return resultBuffer.toString();
            }

        } catch (MalformedURLException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        } catch (IOException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        }
        return null;
    }

2.2.2 傳送POST請求示例程式碼

public static String doPost(String posturl,String params) {

        try {
            //1.通過在 URL 上呼叫 openConnection 方法建立連線物件
            URL url=new URL(posturl);
            HttpURLConnection conn=(HttpURLConnection) url.openConnection();

            //2.處理設定引數和一般請求屬性
            //2.1設定引數
            //可以根據請求的需要設定引數 
            conn.setRequestMethod("POST");
            conn.setUseCaches(false); //是否可以使用快取 不使用快取
            conn.setConnectTimeout(5000);//請求超時時間

            //2.2請求屬性 
            //設定通用的請求屬性 訊息報頭 即設定頭欄位 更多的頭欄位資訊可以查閱HTTP協議
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");

            //2.3設定請求正文 即要提交的資料
            PrintWriter pw=new PrintWriter(new OutputStreamWriter(conn.getOutputStream()));
            pw.print(params);
            pw.flush();
            pw.close();

            //3.使用 connect 方法建立到遠端物件的實際連線。 
            conn.connect();

            //4.遠端物件變為可用。遠端物件的頭欄位和內容變為可訪問。 
            //4.1獲取HTTP 響應訊息獲取狀態碼
            if(conn.getResponseCode()==200)
            {
                //4.2獲取響應的頭欄位
                Map<String, List<String>> headers=conn.getHeaderFields();
                System.out.println(headers); //輸出頭欄位

                //4.3獲取響應正文
                BufferedReader reader = null;
                StringBuffer resultBuffer = new StringBuffer();
                String tempLine = null;

                reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                while ((tempLine = reader.readLine()) != null) {
                    resultBuffer.append(tempLine);
                }
                //System.out.println(resultBuffer);
                reader.close();
                return resultBuffer.toString();
            }
        } catch (MalformedURLException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        } catch (IOException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        }
        return null;
    }
}

相關文章