java.net.URI 簡介 文檔 API


URI 簡介

   
   
   
           
  1. public final class java.net.URI extends Object implements Comparable<URI>, Serializable
表示一個統一資源標識符 (URI) 引用。

除了以下提到的一些細微不同之處外,此類的實例代表一個 URI 引用。此類提供了用於 從其組成部分通過解析其字符串形式創建 URI 實例的構造方法、用於 訪問實例的各個不同組成部分的方法,以及用於 對 URI 實例進行規范化、解析和相對化的方法。此類的實例不可變。

URI 語法和組成部分

在最高級別上,字符串形式的 URI 引用(以下簡寫為 "URI")語法如下
     
     
     
             
  1. [ scheme : ] scheme-specific-part[ # fragment]
其中,方括號 [...] 用於描述可選組成部分,字符 : 和 # 代表它們自身。

絕對 URI 指定了scheme,非絕對的 URI 稱為相對 URI。
URI 還可以根據其是否為不透明的 或分層的 進行分類。

不透明 URI 為絕對 URI,其特定於 scheme 的部分不是以斜線字符 '/' 開始。不透明 URI 無法進行進一步解析。下面是不透明 URI 的一些示例:
     
     
     
             
  1. mailto:java-net@java.sun.com
  2. news:comp.lang.java
  3. urn:isbn:096139210x

分層 URI 或者為絕對 URI(其特定於 scheme 的部分以斜線字符  '/'   開始),或者為相對 URI,即不指定 scheme 的 URI。下面是分層 URI 的一些示例:
     
     
     
             
  1. http://java.sun.com/j2se/1.3/ 
  2. docs/guide/collections/designfaq.html#28 
  3. ../../../demo/jfc/SwingSet2/src/SwingSet2.java 
  4. file:///~/calendar

分層 URI 還要按照下面的語法進行進一步的解析
     
     
     
             
  1. [ scheme :][ // authority][ path][ ? query][ # fragment]
其中, :、 /、 ? 和 # 代表它們自身。
分層 URI 的特定於 scheme 的部分包含 scheme fragment 部分之間的字符。
分層 URI 的授權組成部分(如果指定)為基於服務器的 或基於注冊表的。基於服務器的授權按照如下眾所周知的語法進行解析:
     
     
     
             
  1. [ user-info @] host[ : port]
其中,字符 @ 和 : 代表它們自身。
幾乎當前使用的所有 URI  scheme 都是基於服務器的。不能采用這種方式解析的授權組成部分被視為基於注冊表的。

如果分層 URI 的路徑組成部分以斜線字符 ('/') 開始,則稱此 URI 本身為絕對的;否則它為相對的。分層 URI 或者為絕對的,或者指定了授權的路徑,它始終為絕對的。

如上所述,URI 實例具有以下九個組成部分:
組成部分 類型
  1. 方案Scheme String
  2. 特定於方案的部分SchemeSpecificPart String
  3. 授權Authority String
  4. 用戶信息UserInfo String
  5. 主機Host String
  6. 端口Port int
  7. 路徑Path String
  8. 查詢Query  String
  9. 片段Fragment String 

在給定實例中,任何特殊組成部分都或者為 未定義的,或者為 已定義的,並且有不同的值。未定義的字符串組成部分由 null 表示,未定義的整數組成部分由 -1 表示。已定義的字符串組成部分的值可以為空字符串;這與未定義的組成部分不等效。
實例中特定的組成部分是已定義的還是未定義的取決於所代表的 URI 類型。絕對 URI 具有 scheme 組成部分。不透明的 URI 具有一個 scheme 、一個特定於 scheme 的部分,以及可能會有一個fragment ,但是沒有其他組成部分。分層 URI 總是有一個路徑(盡管可能為空)和一個特定於 scheme 的部分(它至少包含一個路徑),還可以包含任何其他組成部分。如果有授權組成部分且它又是基於服務器的,則主機組成部分將被定義,也有可能定義用戶信息和端口組成部分。

針對 URI 實例的運算

此類支持的主要運算有 規范化、 解析 和 相對化 運算。

1、規范化 是將分層 URI 的路徑組成部分中的不必要的 "." 和 ".." 部分移除的過程。每個 "." 部分都將被移除。".." 部分也被移除,除非它前面有一個非 ".." 部分。規范化對不透明 URI 不產生任何效果。

2、解析 是 根據另一個基本 URI 解析某個 URI 的過程。得到的 URI 由兩個 URI 組成部分構造,構造方式由 RFC 2396 指定,從基本 URI 取出原始 URI 中未指定的組成部分。對於分層 URI,原始的路徑根據基本路徑進行解析,然后進行規范化。

例如,解析 URI-1【 docs/guide/collections/designfaq.html#28】
根據基本 URI【http://java.sun.com/j2se/1.3/】解析,結果為 URI
     
     
     
             
  1. http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html#28

解析相對 URI-2【 ../../../demo/jfc/SwingSet2/src/SwingSet2.java】
根據此結果應生成
     
     
     
             
  1. http://java.sun.com/j2se/1.3/demo/jfc/SwingSet2/src/SwingSet2.java

支持對絕對和相對 URI,以及分層 URI 的絕對和相對路徑的解析。根據任何其他 URI 對 URI file:///~calendar 進行解析只能生成原始的 URI,因為它是絕對路徑。根據相對基礎 URI-1 解析相對 URI-2 將生成規范的但依然是相對的 URI-2 【demo/jfc/SwingSet2/src/SwingSet2.java】

3、相對化 是解析的逆過程:對於任何兩個規范的 URI u 和 v,
     
     
     
             
  1. u .relativize( u .resolve( v )).equals( v )  
  2.  
  3. u .resolve( u .relativize( v )).equals( v )。 
此運算在下面的場合非常有用:構造一個包含 URI 的文檔,該 URI 必須盡可能是根據文檔的基本 URI 建立的相對 URI。
例如,相對化 URI【 http://java.sun.com/j2se/1.3/docs/guide/index.html】
根據基本 URI【 http://java.sun.com/j2se/1.3
生成了相對 URI【docs/guide/index.html】。

字符分類

RFC 2396 精確指出 URI 引用中的各個不同組成部分允許使用的字符。以下分類大部分取自該規范,這些約束的用法描述如下:
  • alpha(初始的) US-ASCII 字母字符,'A' 到 'Z' 以及 'a' 到 'z'
  • digit US-ASCII 十進制數字符,'0' 到 '9'
  • alphanum 所有 alpha 和 digit 字符
  • unreserved(不保留的)     所有 alphanum 字符及字符串 "_-!.~'()*" 中包含的字符
  • punct 字符串 ",;:$&+=" 中包含的字符
  • reserved(保留的) 所有 punct 字符及字符串 "?/[]@" 中包含的字符
  • escaped(轉義的) 轉義八位組,即三部分組合:百分號 ('%') 后跟兩個十六進制數('0'-'9'、'A'-'F' 和 'a'-'f')
  • other 未包含在 US-ASCII 字符集中的 Unicode 字符不是控制字符(根據 Character.isISOControl 方法),並且不是空格字符(根據 Character.isSpaceChar 方法)(與 RFC 2396 有些出入,RFC 2396 限制為 US-ASCII)
全部合法 URI 字符集包含 unreserved、reserved、escaped 和 other 字符。

轉義八位組、引用、編碼和解碼

RFC 2396 允許用戶信息、路徑、查詢和fragment組成部分中包含轉義八位組。轉義在 URI 中實現兩個目的:
  • 當要求 URI 不能包含任何 other 字符以嚴格遵守 RFC 2396 時,需要對非 US-ASCII 字符進行編碼。
  • 要引用 組成部分中的非法字符。用戶信息、路徑、查詢和fragment組成部分在判斷哪些字符合法哪些字符非法上稍有不同。

在此類中由三個相關的運算實現了這兩個目的:
  • 字符的編碼 方式是,用代表該字符在 UTF-8 字符集中的字符的轉義八位組序列取代該字符。例如,歐元符號 ('\u20AC') 編碼后為 "%E2%82%AC"。(與 RFC 2396 有些出入,RFC 2396 未指定任何特殊字符集)。
  • 非法字符通過簡單地對它進行編碼來引用。例如,空格字符,用 "%20" 取代它來進行引用。UTF-8 包含 US-ASCII,因此對於 US-ASCII 字符,此轉換具有的效果與 RFC 2396 的要求相同。
  • 對轉義八位組序列進行解碼 的方法是,用它所代表的 UTF-8 字符集中的字符的序列將它取代。UTF-8 包含 US-ASCII,因此解碼具有對引用的任何 US-ASCII 字符取消引用的效果,以及對任何編碼的非 US-ASCII 字符進行解碼的效果。如果在對轉義八位組進行解碼時出現解碼錯誤,則出錯的八位組用 Unicode 替換字符 '\uFFFD' 取代。

這些運算在此類的構造方法和方法中公開,如下所示:
  • 單參數構造方法要求對參數中的任何非法字符都必須引用,並保留出現的任何轉義八位組和 other 字符。
  • 多參數構造方法根據其中出現的組成部分的需要對非法字符進行引用。百分號字符 ('%') 始終通過這些構造方法引用。任何 other 字符都將被保留。
  • getRawUserInfo、getRawPath、getRawQuery、getRawFragment、getRawAuthority 和 getRawSchemeSpecificPart 方法以原始形式返回它們的相應組成部分的值,不解釋任何轉義八位組。由這些方法返回的字符串有可能包含轉義八位組和 other 字符,但不包含任何非法字符。
  • getUserInfo、getPath、getQuery、getFragment、getAuthority 和 getSchemeSpecificPart 方法解碼相應的組成部分中的任何轉義八位組。由這些方法返回的字符串有可能包含 other 字符和非法字符,但不包含任何轉義八位組。
  • toString 返回帶所有必要引用的 URI 字符串,但它可能包含 other 字符。
  • toASCIIString 方法返回不包含任何 other 字符的、完全引用的和經過編碼的 URI 字符串。

標識

對於 任何 URI u,下面的標識有效
     
     
     
             
  1. new URI( u .toString()) .equals( u ) .
對於不包含冗余語法的任何 URI u,比如在一個空授權前面有兩根斜線(如 file:///tmp/)和主機名后面跟一個冒號但沒有端口(如 http://java.sun.com:),以及除必須引用的字符之外不對字符編碼的情況,下面的標識也有效 (3個參數)
     
     
     
             
  1. new URI( u .getScheme() , u .getSchemeSpecificPart() , u .getFragment()) .equals( u )
在所有情況下,以下標識有效(6個參數,草泥馬的,根本沒有 6個參數的構造方法! ):
     
     
     
             
  1. new URI( u .getScheme() , u .getUserInfo() , u .getAuthority() , u .getPath() , u .getQuery() , u .getFragment()) .equals( u )
如果 u 為分層的,則以下標識有效 (7個參數)
     
     
     
             
  1. new URI( u .getScheme() , u .getUserInfo() , u .getHost() , u .getPort() , u .getPath() , u .getQuery() , u .getFragment()) .equals( u )
如果 u 為分層的並且沒有授權或沒有基於服務器的授權。

URI、URL 和 URN

URI 是統一資源 標識符,而 URL 是統一資源 定位符。因此,籠統地說,每個 URL 都是 URI,但不一定每個 URI 都是 URL。這是因為 URI 還包括一個子類,即統一資源 名稱 (URN),它命名資源但不指定如何定位資源。上面的 mailto、 news 和 isbn URI 都是 URN 的示例。

URI 和 URL 概念上的不同反映在此類和 URL 類的不同中。

此類的實例代表由 RFC 2396 定義的語法意義上的一個 URI 引用。URI 可以是絕對的,也可以是相對的。對 URI 字符串按照一般語法進行解析,不考慮它所指定的 scheme (如果有)不對主機(如果有)執行查找,也不構造依賴於 scheme 的流處理程序。相等性、哈希計算以及比較都嚴格地根據實例的字符內容進行定義。換句話說,一個 URI 實例和一個支持語法意義上的、依賴於 scheme 的比較、規范化、解析和相對化計算的結構化字符串差不多。

作為對照,URL 類的實例代表了 URL 的語法組成部分以及訪問它描述的資源所需的信息。URL 必須是絕對的,即它必須始終指定一個 scheme 。URL 字符串按照其 scheme 進行解析。通常會為 URL 建立一個流處理程序,實際上無法為未提供處理程序的 scheme 創建一個 URL 實例。相等性和哈希計算依賴於 scheme 和主機的 Internet 地址(如果有);沒有定義比較。換句話說,URL 是一個結構化字符串,它支持解析的語法運算以及查找主機和打開到指定資源的連接之類的網絡 I/O 操作。

API

構造方法
  • 1個參數,URI(String str) 通過解析給定的字符串構造一個 URI。
  • 3個參數,URI(String scheme, String ssp, String fragment) 根據給定的組成部分構造 URI。
  • 4個參數,URI(String scheme, String host, String path, String fragment) 根據給定的組成部分構造分層 URI。
  • 5個參數,URI(String scheme, String authority, String path, String query, String fragment) 根據給定的組成部分構造分層 URI。
  • 7個參數,URI(String scheme, String userInfo, String host, int port, String path, String query, String fragment) 根據給定的組成部分構造一個分層 URI。

靜態方法
static URI create(String str)    通過解析給定的字符串創建 URI。
  • 此便捷工廠方法的工作方式類似於調用 URI(String) 構造方法;由該構造方法拋出的任何 URISyntaxException 都被捕獲,並包裝到一個新的 IllegalArgumentException 對象中,然后拋出此對象。
  • 此方法的使用場合是:已知給定的字符串是合法的 URI(例如,程序中聲明的 URI 常量),該字符串無法這樣解析時將被視為編程錯誤。
  • 當 URI 從用戶輸入或從其他易於引起錯誤的源構造時,應該使用直接拋出 URISyntaxException 的構造方法。

get方法-1
對於如下get**()方法,URI 的**組成部分不能包含轉義八位組,因此這些方法不執行任何解碼操作。 
  • String getScheme()    返回此 URI 的方案【Scheme】部分。
    • URI 的方案組成部分(如果定義了)只包含 alphanum 類別和字符串 "-.+" 中的字符。
    • 方案始終以 alpha 字符開始。
  • int getPort()    返回此 URI 的【端口號】。
    • URI 的端口組成部分(如果定義了)是一個非負整數。
    • 如果端口未定義,則返回 -1
  • String getHost()    返回此 URI 的【主機】組成部分。 

get方法-2
對於如下get**()方法,除了轉義八位組的所有序列都已解碼之外,其和對應的getRaw**()方法返回的字符串相等。
  • String getRawPath()    返回此 URI 的原始/已解碼的【路徑】組成部分。
    • 如果路徑未定義,則返回 null 
  • String getRawAuthority()    返回此 URI 的原始/已解碼的授權組成部分。
    • URI 的授權組成部分(如果定義了)只包含“商用 at”字符 ('@') 和 unreserved、punct、escaped 和 other 類別中的字符。
    • 如果授權是基於服務器的,則它被進一步約束為具有有效的用戶信息、主機和端口組成部分。
  • String getRawFragment()    返回此 URI 的原始/已解碼的片段組成部分。
  • String getRawQuery()    返回此 URI 的原始/已解碼的查詢組成部分。
  • String getRawSchemeSpecificPart()    返回此 URI 原始的特定於方案的解碼部分(從不為 null)
    • 特定於方案的部分永遠不會是未定義的,但它可能為空("")。
    • URI 的特定於方案的部分只包含合法的 URI 字符。
  • String getRawUserInfo()    返回此 URI 的原始/已解碼的用戶信息組成部分。
    • URI 的用戶信息組成部分(如果定義了)只包含 unreserved、punct、escaped 和 other 類別中的字符。

其他方法
  • boolean isAbsolute()    判斷此 URI 是否為絕對的。
    • 當且僅當 URI 具有方案組成部分時,它才是絕對的。
  • boolean isOpaque()    判斷此 URI 是否為不透明的。
    • 當且僅當 URI 是絕對的且其特定於方案的部分不是以斜線字符 ('/') 開始時,此 URI 才是不透明的。
    • 不透明的 URI 具有一個方案、一個特定於方案的部分,以及可能會有的一個片段;所有其他組成部分都是未定義的。
  • String toASCIIString()    以 US-ASCII 字符串形式返回此 URI 的內容。
    • 如果此 URI 未包含 other 類別的任何字符,則調用此方法將返回的值與調用 toString 方法返回的值相同。否則,此方法的工作方式類似於調用該方法,然后對結果進行編碼。
  • URL toURL()    根據此 URI 構造一個 URL。
    • 首先檢查得知此 URI 為絕對路徑后,此便捷方法的工作方式就好像調用它與對表達式 new URL(this.toString()) 進行計算是等效的。
    • 如果此 URL 不是絕對的,拋出 IllegalArgumentException;如果無法找到 URL 的協議處理程序,或者如果在構造 URL 時發生其他錯誤,拋出MalformedURLException 。

URI的一些運算(規范化、相對化 、解析
  • URI normalize()    規范化此 URI 的路徑。
  • URI relativize(URI uri)    根據此 URI 將給定 URI 相對化。
  • URI parseServerAuthority()    嘗試將此 URI 的授權組成部分(如果已定義)解析為用戶信息、主機和端口組成部分。
  • URI resolve(URI uri)    根據此 URI 解析給定的 URI。
  • URI resolve(String str)    解析給定的字符串,然后在此 URI 的基礎上構造一個新的 URI。 此方法與進行 resolve(URI.create(str)) 的作用相同。
2017-7-29





免責聲明!

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



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