URL 是我們每天暢游在互聯網世界中最最常見的東西了,對于普通用戶來說,URL 就是一個字符串,比如 http://www.justdoJAVA.com ,但是對于我們開發者而言,除了 URL,還有一個東西叫做 URI,很多人經常搞不清楚這兩個概念,本文我們就從這個話題開始。
從 URN 開始
在介紹這兩個東西之前,我們還得先說說另外一個東西,叫做URN,URN的全程為Uniform Resource 譯作統一資源名稱,URN、URL與URI的關系類似于下圖:
由上圖可以看到,URN 和 URL 實際上是 URI 范疇之內的概念。URN 表示給每一個互聯網資源取一個名字,但是互聯網資源千千萬萬,給每一個資源取一個不重復的名字顯然不太現實,因此,并不是所有的互聯網資源都有 URN ,URN 就類似于一個人的身份證號碼,是唯一的,但是通過這個身份證號碼找不到這個人,要找到這個人我們得通過類似于下面這種地址 “中國/廣東省/廣州市/天河區/馬場路/南國花園/8棟/1203室” ,這種能夠查找到某一個資源的字符串就是 URL ,URL 全稱叫做 Uniform Resource Locator ,譯作統一資源定位符,表示一個資源的地點。
URL 與 URI
URI 是 Uniform Resource Identifier 的縮寫,譯作統一資源標識符,RFC2396 中對這三個單詞做了如下定義:
Uniform
規定統一的格式可方便處理多種不同類型的資源,而不用根據上下文環境來識別資源指定的訪問方式。另外,加入新增的協議方案(如 http: 或 ftp:)也更容易。
Resource
資源的定義是“可標識的任何東西”。除了文檔文件、圖像或服務(例如當天的天氣預報)等能夠區別于其他類型的,全都可作為資源。另外,資源不僅可以是單一的,也可以是多數的集合體。
Identifier
表示可標識的對象。也稱為標識符。
由此可見,URI 就是由某個協議方案表示的資源的定位標識符,而協議方案就是訪問資源時所采用的協議類型的名稱,比如我們采用 HTTP 協議時,協議方案就是 HTTP ,我們采用 FTP 協議時,協議方案就是 FTP ,另外還有 file、mailto、telnet 等
按照 RFC3986 的說法,一個 URI 可以被進一步歸類為一個定位器(URL),一個名字(URN),或兩者都是。也就是說 URI 可以是 URL ,也可以是 URN 或兩者兼備,如果你關心資源的名稱,那就將 URI 定義成 URN 的形式,如果你關心資源的位置,那么就將 URI 定義成 URL 的形式,URI 中包括了 URN 和 URL 。在 RFC3986 文檔中還有如下一句話:
"Future specifications and related documentation should use the general term "URI" rather than the more restrictive terms "URL" and "URN""
這句話告訴我們未來應該使用更加通用的 URI 術語,而不是受限制頗多的 URL 和 URN 。
前面介紹了 URI ,接下來我們再來探討下 URI 的格式(基于前文得出的結論,下面涉及到的地址我將都以 URI 來稱呼)。
URI 的格式
對于普通用戶,說 URI 他們可能有點懵,但是說 http 開頭的那個字符串肯定都知道是什么了,我們常見的網址除了 http: 開頭之外,也有 ftp: 開頭的,也有 mailto: 開頭的,分別代表不同的含義,這是因為瀏覽器的功能不僅僅局限于訪問 web 服務器,也可以用來訪問 ftp 服務器,也可以用來瀏覽本地文件,也可以用來發送郵件,因此瀏覽器需要有一個東西來判斷使用哪種功能來訪問相應的數據,因此有了協議,也有了各種各樣不同的 URI 。如下圖是一個完整的URI:
這其中用戶名、密碼和端口號都可以省略,在瀏覽器拿到這樣一個 URI 之后,首先會對其進行解析,比如上面這個地址,瀏覽器經過解析之后,知道要去獲取 www.baidu.com 服務器上的 /folder/index.html 文件。不過,在實際應用中,有的時候 URI 并不是這么清晰,比如下面這個:
http://wwww.baidu.com
這種 URI 并沒有直接指定要訪問哪個文件,像這種沒有路徑的情況,就代表訪問根目錄下預先設置的默認文件,一般就是 /index.html,/default.html 一類的文件,在 Java 中,我們也可以在 web.xml 中來配置這個默認文件。
有的時候我們還有可能遇到下面這種地址:
http://www.baidu.com/folder/
這個 URI 以一個 / 結尾,表示 folder 是一個目錄,我們要訪問的是這個目錄下的文件,但是又沒有說明是這個目錄下的哪個文件,此時依然是采用該目錄下 index.html 或者 default.html 一類的文件。
有的時候,我們還可以看到下面這種 URI:
http://www.baidu.com/folder
即 folder 后面沒有 /,此時會先將 folder 當作一個資源去訪問(比如一個名為 folder 的 Servlet ),如果沒有名為 folder 的資源,那么瀏覽器會自動在 folder 后面加上一個 / ,此時地址變為 http://www.baidu.com/folder/ ,folder 是一個目錄,然后就會去嘗試訪問 folder 目錄下的 index.html 或者 default.html。
注意這種自動調整只在瀏覽器中存在,如果你的項目是一個手機 App 或者你是一個 Ajax 請求,則不會有這種調整,即沒寫 / 就當做具體資源來對待,如果該資源不存在,就會報 404 ,寫了/ 就當目錄來對待。(OkHtpp3中是這樣)
有的時候我們還可能見到下面這種URI:
http://www.baidu.com/
這個和我們介紹的第一種情況很類似,只是后面多了一個 / ,這個 / 表示我們要訪問的是根目錄,但是沒有指定根目錄下的文件,默認就是根目錄下的 index.html 或者 default.html。
OK,經過上面的介紹,小伙伴對 URI 最后面的 / 已經有了清晰的認識了吧?這個東西不可以隨意省略,有 / 和沒有 / ,訪問結果有可能是天壤之別。
參考資料:
1. 《網絡是怎樣連接的》