天天看點

關于 URL,說幾個你不知道的點!

java.net.URL

類将 URL 位址進行了封裝,并提供了解析 URL 位址的基本方法,比如擷取 URL 的主機名和端口号。

java.net.URLConnection

則代表了應用程式和 URL 之間的通信連結,可用于讀取和寫入此 URL 引用的資源。

URLConnection 看起來隻是比 URL 多了一個 Connection,它們之間的關系也僅限于此嗎?

01、什麼是 URL

為了搞清楚什麼是 URL,需要引入另外兩個概念 URI 和 URN。

什麼鬼,URL 都沒搞清楚,又來兩個搞不清楚的?别擔心,我能像變了魔法一樣讓大家把三個都搞清楚。

  • URI = Universal Resource Identifier,中文釋義為統一資源标志符
  • URL = Universal Resource Locator,中文釋義為統一資源定位符
  • URN = Universal Resource Name,中文釋義為統一資源名稱

它們之間的關系如下圖所示:

關于 URL,說幾個你不知道的點!

這圖啥意思啊,怎麼辦呢?張小敬有問題就去問葛佬,咱不會就去問“維基百科”啊。

URI 可以分為 URL 和 URN,或者是 URL 和 URN 的結合體(同時具備 Locator 和 Name)。URN 就好像一個人的名字,URL 就像一個人的位址。換句話說:URN 确定了身份,URL 提供了找到它的方式。

概念清晰了吧?URI 是一個純粹的句法結構,用于指定辨別 Web 資源的字元串的各個不同部分。URL 是 URI 的一個特例,包含了定位 Web 資源的足夠多的資訊。URI 是統一資源辨別符,而 URL 是統一資源定位符。URL 是 URI 的一種,比如:http://www.itmind.net/。但不是所有的 URI 都是 URL,因為 URI 可能包括一個子集,即統一資源名稱 (URN,命名了資源但不指定如何定位資源),比如說:mailto:[email protected]

吧啦吧啦說這麼多挺累的,來一發執行個體吧,用于擷取 URL 的主機名和端口号。

URL url = new URL("http://www.itmind.net/category/payment-selection/zhishixingqiu-jingxuan/");

System.out.println("host: " + url.getHost());
System.out.println("port: " + url.getPort());
System.out.println("uri_path: " + url.getPath());

// 輸出
// host: www.itmind.net
// port: -1
// uri_path: /category/payment-selection/zhishixingqiu-jingxuan/
           

複制

1)建立

java.net.URL

對象的方法非常簡單,隻需要一行代碼。

URL url = new URL(URL位址);
           

複制

URL 對象是不可變的,因為 URL 類是 final 類型的,這樣的好處就是保證它是"線程安全"的。

2)有了

java.net.URL

對象後,就可以擷取 URL 相關的主機名、端口、路徑等等。

url.getHost()
url.getPort()
url.getPath()
           

複制

02、什麼是 URLConnection

URLConnection 是一個抽象類,代表應用程式和 URL 之間的通信連結。它的執行個體可用于讀取和寫入此 URL 引用的資源。該類提供了比 Socket 類更易于使用、更進階的網絡連接配接抽象。

怎麼擷取 URLConnection 對象呢?通過 URL 對象的

openConnection()

方法,示例如下。

URL url = new URL("http://www.itmind.net");
URLConnection connection = url.openConnection();
           

複制

如果 URL 協定為 HTTP 的話,傳回的連接配接為 URLConnection 的子類 HttpURLConnection。

有了

URLConnection

對象後,可以通過

getInputStream()

傳回一個 InputStream,由此讀取 URL 所引用的資源資料(如果讀取 ASCII 文本則為 ASCII;如果讀取 HTML 檔案則為原始 HTML,如果讀取圖像檔案則為二進制圖檔資料等)。

我們來嘗試讀取一下小白學堂首頁的内容,代碼示例如下。

URL url = new URL("http://www.itmind.net");
URLConnection connection = url.openConnection();

try (InputStream in = connection.getInputStream();) {

	ByteArrayOutputStream output = new ByteArrayOutputStream();
	byte[] buffer = new byte[1024];
	int len = -1;
	while ((len = in.read(buffer)) != -1) {
		output.write(buffer, 0, len);
	}

	System.out.println(new String(output.toByteArray()));

} catch (IOException e) {
	e.printStackTrace();
}
           

複制

可以使用

try-with-resource

擷取

InputStream

,該類實作了

AutoCloseable

接口,可以在内容讀取完畢後自動關閉輸入流。

列印的内容如下圖所示(部分):

關于 URL,說幾個你不知道的點!

如果你想讀取某個 URL 的内容,上述方法是一個不錯的方案,趕快去試試吧!

03、URL 和 URLConnection 的不同

URL 和 URLConnection 最大的不同在于:

  • URLConnection 提供了對 HTTP 頭部的通路;
  • URLConnection 可以配置發送給某個 URL 的請求參數;
  • URLConnection 不僅可以讀取 URL 定位的資源,還可以向其寫入資料。

擷取 HTTP 頭部的方法有以下一些:

  • getContentType,傳回 Content-type 頭字段的值,即資料的 MIME 内容類型。若類型不可用,則傳回 null。如果内容類型是文本,則 Content-type 首部可能會包含一個辨別内容編碼方式的字元集,例如:

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

  • getContentLength(),傳回 Content-length 頭字段的值,即内容的位元組數。
  • getContentEncoding(),傳回 Content-encoding 頭字段的值,即内容的編碼方式(不同于字元編碼方式),例如:x-gzip。
  • getDate(),傳回 date 頭字段的值,即請求的發送時間。
  • getExpiration(),傳回 expires(過期時間) 頭字段的值。如果傳回 0,表示不過期,永遠緩存。
  • getLastModified(),傳回 last-modified(上次修改日期) 頭字段的值。

代碼示例如下。

URL url = new URL("http://www.itmind.net");
URLConnection connection = url.openConnection();
System.out.println(connection.getContentType());
System.out.println(connection.getContentLength());
System.out.println(connection.getContentEncoding());
System.out.println(connection.getDate());
System.out.println(connection.getExpiration());
System.out.println(connection.getLastModified());

// 輸出
// text/html; charset=UTF-8
// -1
// null
// 1566886980000
// 0
// 0
           

複制