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