URLConnection類詳解


https://www.cnblogs.com/shijiaqi1066/p/3753224.html

1. URLConnection概述

URLConnection是一個抽象類,表示指向URL指定資源的活動連接。

URLConnection類本身依賴於Socket類實現網絡連接。一般認為,URLConnection類提供了比Socket類更易於使用、更高級的網絡連接抽象。但實際上,大多數程序員都會忽略它。因為URLConnection太貼近HTTP協議。它假定傳輸的內容前面都有MIME首部或類似的東西。但大多數協議(如FTP和SMTP)並不使用MIME首部。

 

URLConnection繼承樹查看如下:

wps_clip_image-6273

URLConnection類聲明為抽象類,除了connect()方法,其他方法都已經實現。URLConnection的三個實現子類都位於sun.net.www包下。 

URLConnection類的保護類型的構造方法:

protected URLConnection(URL url)

  構造一個到指定 URL 的 URL 連接。 

connect()方法由子類實現本地與服務器的連接方式。一般使用TCP socket,但也可以使用其他其他機制來建立。

abstract  void connect()

  打開到此 URL 引用的資源的通信鏈接(如果尚未建立這樣的連接)。 

當派生URLConnection子類時,通常會覆蓋URLConnection的其他方法,使其返回有意義的值。 

URLConnection類聲明為抽象類,除了connect()方法,其他方法都已經實現。URLConnection的三個實現子類都位於sun.net.www包下。

1.1 讀取首部

String getContentType()

  返回 Content-type 頭字段的值。即數據的MIME內容類型。若類型不可用,則返回null。

  除了HTTP協議,極少協議會使用MIME首部。若內容類型是文本。則Content-type首部可能會包含一個標識內容編碼方式的字符集。

例:Content-type:text/html; charset=UTF-8

 

int getContentLength()

  返回 Content-length 頭字段的值。該方法獲取內容的字節數。許多服務器只有在傳輸二進制文件才發送Content-length首部,在傳輸文本文件時並不發送。若沒有該首部,則返回-1。

  若需要知道讀取的具體字節數,或需要預先知道創建足夠大的緩沖區來保存數據時,可以使用該方法。

 

String getContentEncoding()

  返回 Content-encoding 頭字段的值。獲取內容的編碼方式。若內容無編碼,則該方法返回null。

  注意:Content-encoding(內容編碼)與字符編碼不同。字符編碼方式由Content-type首部或穩定內容的信息確定,它指出如何使用字節指定字符。內容編碼方式則指出字節如何編碼其他字節。

例:若編碼格式為x-gzip,則可以使用java.util.zip.GZipInputStream來解碼。

 

long getDate()

  返回 date 頭字段的值。獲取請求的發送時間。即自1900年1月1日子夜后過去的毫秒數。

  注意:這是從服務器的角度看到的發送時間。可能與本地時間不一致。若首部不包括Date字段,則返回0。

 

long getExpiration()

  返回 expires 頭字段的值。獲取Expires的值。若無該字段,則返回0。0即表示不過期,永遠緩存。

  注意:該值是自1970年1月1日上午12:00后的毫秒數。

 

long getLastModified()

  返回 last-modified 頭字段的值。該值是自1900年1月1日子夜后過去的毫秒數。若無該字段,則返回0。

1.2 獲取任意首部字段

String getHeaderField(String name)

  返回指定的頭字段的值。

 

Map<String,List<String>> getHeaderFields()

  返回頭字段的不可修改的 Map。

 

String getHeaderFieldKey(int n)

  返回第 n 個頭字段的鍵。

 

String getHeaderField(int n)

  返回第 n 個頭字段的值。

 

long getHeaderFieldDate(String name, long Default)

  返回解析為日期的指定字段的值。

 

int getHeaderFieldInt(String name, int Default)

  返回解析為數字的指定字段的值。

1.3 配置連接

URLConnection類的保護類型字段如下:

protected  URL url

  該字段指定URLConnection連接的URL。構造函數會在創建URLConnection時設置,此后就不能再改變。

 

protected  boolean connected

  當連接打開時,該字段為true。若連接關閉,則為false。沒有直接讀取或改變connected值的方法。任何導致URLConnection連接的方法都會將此變量設為true,包括connect(),getInputStream(),和getOutputStream()。

  任何導致URLConnection斷開的方法都會將此字段設為false。

  java.net.URLConnection沒有斷開方法,但一些子類,如java.net.HttpURLConnection中存在這樣的方法。

 

protected  boolean allowUserInteraction

  該字段表示是否允許與用戶交互。默認為false,即不允許交互。該值只能在URLConnection連接前設置。

例:Web瀏覽器可能需要訪問用戶名和口令。

 

protected  boolean doInput

  該字段在URLConnection可用於輸入時為true,否則為false。默認為true。

 

protected  boolean doOutput

  該字段在URLConnection可用於輸出時為true,否則為false。默認為false。

 

protected  long ifModifiedSince

  該字段指示了將放置If-Modified-Since首部字段中的日期(格林威治標准時間1970年1月1日子夜后的毫秒數)。

 

protected  boolean useCaches

  該字段指定了是否可以在緩存可用時使用緩存。默認為true,表示緩存將被使用;false表示緩存不被使用。

以上字段定義了客戶端如何向服務器作出請求。這些字段只能在URLConnection連接前修改。否則拋出IllegalStateException異常。

每個字段都有一些相應的方法。

以上字段定義了客戶端如何向服務器作出請求。這些字段只能在URLConnection連接前修改。否則拋出IllegalStateException異常。

每個字段都有一些相應的方法。

  • URL getURL()
  • void setDoInput(boolean doinput)
  • boolean getDoInput()
  • void setDoOutput(boolean dooutput)
  • boolean getDoOutput()
  • void setUseCaches(boolean usecaches)
  • boolean getUseCaches()
  • void setAllowUserInteraction(boolean allowuserinteraction)
  • boolean getAllowUserInteraction()
  • void setIfModifiedSince(long ifmodifiedsince)
  • long getIfModifiedSince()

還有一些方法,這些方法用於定義和獲取URLConnection對象的默認行為:

  • static boolean getDefaultAllowUserInteraction()
  • boolean getDefaultUseCaches()
  • void setDefaultUseCaches(boolean defaultusecaches)
  • static void setDefaultAllowUserInteraction(boolean defaultallowuserinteraction)
  • static void setFileNameMap(FileNameMap map)
  • static FileNameMap getFileNameMap()

 

1.4 關於超時

Java 1.5增加了如下4個方法,允許查詢和修改連接的超時值。即底層socket在拋出SocketTimeoutException異常前等待遠端響應時間。

設置獲取讀取的超時值,單位為毫秒。

int getReadTimeout()

void setReadTimeout(int timeout)

  設置獲取連接的超時值,單位為毫秒。

 

int getConnectTimeout()

void setConnectTimeout(int timeout)

  這四個方法將0解釋為永不超時。如果超時值為負數。兩個設置方法都會拋出IllegalArgumentException異常。

 

 

1.5 配置HTTP首部

客戶端向服務器發送請求,不僅會發送請求行,還發送首部。Web服務器可以根據此信息向不同客戶端提供不同的頁面,獲取和設置cookie,通過口令設置用戶等等。通過在客戶端發送和服務器響應的首部中放置不同的字段,就可以完成這些工作。

每個URLConnection的具體子類都在首部中設置一些默認的鍵值對(實際上只有HttpURLConnection這樣做,因為HTTP是唯一以這種方式使用首部的主要協議。)

通過以下方法可以設置URLConnection在打開連接增加HTTP首部:

void setRequestProperty(String key, String value)

  此方法只在連接打開之前打開,將會拋出IllegalStateException異常。但該方法僅支持對一個首部設置一個值。

 

HTTP允許一個熟悉有多個值。各個值之間用逗號隔開。

例:cookie:username=sjq; session=hdfu23asdjf901j;

 

使用如下方法為首部增加值:

void addRequestProperty(String key, String value)

  該方法用於添加某個指定首部字段的值。

 

使用如下方法獲取首部字段:

String getRequestProperty(String key)

Map<String,List<String>> getRequestProperties()

  以上方法用於獲取URLConneciton所擁有HTTP首部。 

 

1.6 使用URLConnection與服務器交互

InputStream getInputStream()

  返回從此打開的連接讀取的輸入流。

OutputStream getOutputStream()

  返回寫入到此連接的輸出流。

 

若只是向服務器請求數據,則為HTTP請求方法為GET。

若需要向服務器提交數據,必須在先調用setDoOutput(true)。當doOutput屬性為true時,請求方法將由GET變為POST。

 

@Test
public void test(){
    try {
        URL url = new URL("http://www.baidu.com");
        URLConnection uc = url.openConnection();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

例:使用URLConnection請求Baidu首頁。

該程序請求方法為get。使用getInputStream()方法輸出的內容只有響應體,不包含響應的首部。

@Test
public void testGetInputStream(){
    InputStream in = null;
    try {
        //連接
        URL url = new URL("http://www.baidu.com");
        URLConnection uc = url.openConnection();
         
        //獲取讀入流
        in = uc.getInputStream();
        //放入緩存流
        InputStream raw = new BufferedInputStream(in);
        //最后使用Reader接收
        Reader r = new InputStreamReader(raw);
         
        //打印輸出
        int c;
        while((c = r.read())>0){
            System.out.print((char)c);
        }
         
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally{
        try {
            if(in!=null){
                in.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}   

1.6 獲得內容

Object getContent()

  該方法實質上與URL類的getContent()方法相同。使用該方法JVM需要識別和理解該內容類型。該方法只用於支持類似HTTP的協議,協議需要對MIME內容類型有較清楚的了解。若內容未知,或協議無法理解內容類型,getContent()會拋出一個UnknowServiceException異常。

Object getContent(Class[] classes)

  該方法可以選擇將內容轉換為哪個類對象,以提供數據的不同對象表示。該方法嘗試以classes數組中某個類的形式返回內容。優先順序就是數組的順序。若任何一種請求類型都不可用,此方法會返回null。

 

 

1.7 ContentHandlerFactory

URLConnection類包括一個靜態的ContentHandler。即內容處理器。通過以下方法設置內容處理器工廠。

static void setContentHandlerFactory(ContentHandlerFactory fac)

 

1.8 URLConnection的安全

建立網絡連接、讀寫文件等等存在一些安全限制,URLConnection對象會受到這些安全限制的約束。

Permission getPermission()

  該方法返回Permission對象,指出連接此URL所需的許可權。如果沒有所需的許可權(即沒有適當的安全管理器),它就會返回null。 

1.9 猜測MIME內容類型

static String guessContentTypeFromName(String fname)

  根據 URL 的指定 "file" 部分嘗試確定對象的內容類型。

static String guessContentTypeFromStream(InputStream is)

  根據輸入流的開始字符嘗試確定輸入流的類型。

2. HttpURLConnection

java.net.HttpURLConnection類是URLConnection的抽象子類;它提供了一些有助於專門操作http URL的額外方法。

sun.net.www.protocol.http包中也提供了一個HttpURLConnection類。該類實現了抽象的connect()方法。但一般很少直接訪問該類。

 

2.1 獲取HttpURLConnection對象

@Test
void testHttpURLConnection(){
    try {
        URL url = new URL("http:www.baidu.com");
        URLConnection urlConnection = url.openConnection();
        HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection;
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

2.2 請求方法

HTTP協議提供了7中請求方法:

  • GET
  • POST
  • HEAD
  • PUT
  • OPTIONS
  • DELETE
  • TRACE

通過以下方法設置請求方法:

void setRequestMethod(String method)

若請求不是7個方法的字符串,則會拋出java.net.ProtocolException異常。一般只設置請求方法是不夠的,還需要調整HTTP首部,還要提供消息體。

以下方法獲取HTTP請求方法

String getRequestMethod()

 

 

2.3 斷開與服務器的連接

HTTP的Keep-Alive對Web連接的性能有所提升,允許多個請求和響應通過一個TCP連接連續發送。

客戶端通過HTTP請求首部包含Connection字段及Keep-Alive,表示客戶端願意使用Keep-Alive:

  Connection: Keep-Alive

 

但當使用Keep-Alive時,服務器不再因為向客戶端發送最后一個字節數據就關閉連接。畢竟客戶端還可能發送另一個請求。因此客戶端需要復雜關閉連接。

Java提供如下方法關閉連接,實際上很少使用該方法:

abstract  void disconnect()

 

2.4 獲取請求

如果HTTP響應狀態為4xx(客戶端錯誤)或者5xx(服務器錯誤),你可以通過HttpUrlConnection.getErrorStream()來查看服務器發送過來的信息。

InputStream getErrorStream()

 

例:

InputStream error = ((HttpURLConnection) connection).getErrorStream();

 

如果HTTP響應狀態為-1,就是出現了連接錯誤。HttpURLConnection會保持連接一直可用,如果你想關閉這個特性,需要把http.keepAlive設置為false:

System.setProperty("http.keepAlive", "false");

 

 

2.5 Http響應碼

HTTP響應的第一行被稱為消息響應。該信息不會被URLConnection的getHeaderFiled()方法讀取。

String getResponseMessage()

  返回消息響應。如:HTTP/1.1 404 Not Found

int getResponseCode()

  返回消息響應碼。如:404。

HttpURLConnection類提供了常見響應碼常量。具體請參考JDK文檔。

 

 

2.6 重定向

默認情況下,HttpURLConnection類會跟蹤重定向。但HttpURLConnection有兩個靜態方法,可以確定是否跟隨重定向。

static void setFollowRedirects(boolean set)

static boolean getFollowRedirects()

  若跟隨,則為true,否則為false。

 

這兩個是靜態方法,它們會改變該方法后構造的所有HttpURLConnection對象的行為。若安全管理器不允許其改變,則會拋出SecurityException異常。

 

也可以對某個HttpURLConnection實例設置是否重定向。

void setInstanceFollowRedirects(boolean followRedirects)

boolean getInstanceFollowRedirects()

 

 

2.7 代理

HttpURLConnection可以得知請求是否通過了代理服務器。

使用如下方法:

abstract  boolean usingProxy()

 

2.8 流模式

每個發送給HTTP服務器的請求都有HTTP首部。首部中有一個Content-type字段;即請求體中的字節數。首部位於主體的前面。但是,為了寫入首部,需要知道主體的長度,而在寫首部的時候可能還不知道主題的長度。一般情況下Java對此兩難境地的解決辦法是,對於從HttpURLConnection獲取的OutputStream,緩存寫入到此OutputStream中的所有內容,直到流被關閉。到這時,它就知道了主題中有多少字節,

在請求發送之前,HttpURLConnetion會把所有需要發送的數據放到緩沖區里,不管你是否使用connection.setRequestProperty("Content-Length", contentLength);設置了contentLength,當你並行發送大量的POST請求時,這可能會引起OutOfMemoryExceptions 異常,為了避免這個問題,需要使用如下方法:

void setFixedLengthStreamingMode(int contentLength)

  此方法用於在預先已知內容長度時啟用沒有進行內部緩沖的 HTTP 請求正文的流。

例:

httpConnection.setFixedLengthStreamingMode(contentLength);

 

但是如果不能事先知道內容的長度,可以使用HttpURLConnection.setChunkedStreamingMode()方法設置為塊狀流模式。在塊狀流模式的情況下,放在塊里的內容將會被強行發送出去。下邊的例子將會把發送的內容按照每塊1KB的大小發送出去。

void setChunkedStreamingMode(int chunklen)

  此方法用於在預先不知道內容長度時啟用沒有進行內部緩沖的 HTTP 請求正文的流。

 

例:

httpConnection.setChunkedStreamingMode(1024);

 

 

2.9 緩存

默認情況下,Java 1.5不返回任何數據。但通過派生java.net.ResponseCache類的子類,並安裝為系統默認值,就可以創建自己的緩存。無論系統合適嘗試通過協議處理器加載新的URL,它將首先在緩存中查找,若緩存找到了所需的內容,就不需要連接遠程服務器了。若緩存數據不存在,則下載相應數據,並將其放入緩存中。

 


免責聲明!

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



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