<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 495,comments - 227,trackbacks - 0
    URI、URL和URN是識別、定位和命名互聯(lián)網(wǎng)上的資源的標(biāo)準(zhǔn)途徑。本文分析了URI、URL和URN和Java API的URI和URL類(以及與URL相關(guān)的類),并演示了如何在程序中使用這些類。
      1989年Tim Berners-Lee發(fā)明了互聯(lián)網(wǎng)(World Wide Web)。WWW被認為是全球互連的實際的和抽象的資源的集合--它按需求提供信息實體--通過互聯(lián)網(wǎng)訪問。實際的資源的范圍從文件到人,抽象的資源包括數(shù)據(jù)庫查詢。因為要通過多樣的方式識別資源(人的名字可能相同,然而計算機文件只能通過唯一的路徑名稱組合訪問),所以需要標(biāo)準(zhǔn)的識別WWW資源的途徑。為了滿足這種需要,Tim Berners-Lee引入了標(biāo)準(zhǔn)的識別、定位和命名的途徑:URI、URL和URN。
      URI、URL和URN是什么?
      體系中的URI、URL和URN是彼此關(guān)聯(lián)的。URI的范疇位于體系的頂層,URL和URN的范疇位于體系的底層。這種排列顯示URL和URN都是URI的子范疇,如圖1所示:

    圖1:
    ?
    URI、URL和URN之間的層次關(guān)系。URL和URN是URI的子范疇。
      URI表示的是統(tǒng)一的資源標(biāo)識,它是以某種統(tǒng)一的(標(biāo)準(zhǔn)化的)方式標(biāo)識資源的簡單字符串。典型情況下,這種字符串以scheme(命名URI的名字空間的標(biāo)識符--一組相關(guān)的名稱)開頭,語法如下:
      [scheme:] scheme-specific-part
      URI以scheme和冒號開頭。Scheme用大寫/小寫字母開頭,后面為空或者跟著更多的大寫/小寫字母、數(shù)字、加號、減號和點號。冒號把scheme與scheme-specific-part分開了,并且scheme-specific-part的語法和語義(意思)由URI的名字空間決定。其中一個例子是http://www.cnn.com,其中http是scheme,//http://www.cnn.com是 scheme-specific-part,并且它的scheme與scheme-specific-part被冒號分開了。
    我們可以把URI按照絕對的或相對的分類。絕對的URI指以scheme(后面跟著冒號)開頭的URI。前面提到的http://www.cnn.com就是絕對的URI的一個例子,其它的例子還有mailto:jeff@javajeff.comnews:comp.lang.java.help和xyz://whatever。你可以把絕對的URI看作是以某種方式引用某種資源,而這種方式對標(biāo)識符出現(xiàn)的環(huán)境沒有依賴。如果使用文件系統(tǒng)作類比,絕對的URI類似于從根目錄開始的某個文件的路徑。與絕對的URI不同的,相對的URI不是以scheme(后面跟著冒號)開始的URI。它的一個例子是articles/articles.html。你可以把相對的URI看作是以某種方式引用某種資源,而這種方式依賴于標(biāo)識符出現(xiàn)的環(huán)境。如果用文件系統(tǒng)作類比,相對的URI類似于從當(dāng)前目錄開始的文件路徑。
    URI可以進一步分為不透明的和分層的兩類。不透明的URI指scheme-specific-part不是以正斜杠(/)開頭的絕對的URI。其例子有news:comp.lang.java和前面的mailto:jeff@javajeff.com。不透明的URI并不是用于分解的(超出了識別scheme的范疇),因為不需要驗證scheme-specific-part的有效性。與它不同的是,分層的URI可以是以正斜杠開頭的絕對的URI或相對的URL。
      與不透明的URI不同,分層的URI的scheme-specific-part必須被分解為幾個組成部分。這些組成部分是什么?分層的URI標(biāo)識組件的普通子集的scheme-specific-part符合下面的語法:
      [//authority] [path] [?query] [#fragment]
      可選的authority組件標(biāo)識了該URI名字空間的命名機構(gòu)。如果有這一部分,它就是以一對正斜杠開始的,它可以是基于服務(wù)器或基于注冊的,并且它以后面的正斜杠、問號或沒有其它符號結(jié)束。基于注冊的授權(quán)機構(gòu)組件有特定大綱的語法(本文沒有討論,因為很少使用它),而基于服務(wù)器的授權(quán)機構(gòu)組件的語法如下:
      [userinfo@] host [:port]
      按照這種語法,基于服務(wù)器的授權(quán)機構(gòu)組件可以隨意的以用戶信息(例如用戶名)開始,后面跟著一個@符號,緊接著是主機的名稱,以及冒號和端口號。例如jeff@x.com:90就是一個基于服務(wù)器的授權(quán)機構(gòu)組件,其中jeff包含了用戶信息,x.com包含了主機,90包含了端口。
      可選的path組件根據(jù)授權(quán)機構(gòu)組件(如果提供了)或大綱(如果沒有授權(quán)機構(gòu)組件)識別資源的定位(或位置)。路徑(path)可以分成一系列的路徑片斷(path segment),每個路徑片斷使用正斜杠與其它的路徑片斷隔開。如果路徑的第一個路徑片斷以一個正斜杠開始,該路徑就被認為是絕對的。否則路徑就被認為是相對的。例如,/a/b/c由三個路徑片斷--a、b和c組成了一個路徑,此外,這個路徑是絕對的,因為第一個路徑片斷(a)的前綴是正斜杠。
      可選的query組件識別要傳遞給某種資源的數(shù)據(jù)。這種資源使用該數(shù)據(jù)獲取或生成其它的傳遞回調(diào)用者的數(shù)據(jù)。例如,http://www.somesite.net/a?x=y, x=y就是一個查詢(query),在這個查詢中,x=y是傳遞給某種資源的數(shù)據(jù)--x是某種實體的名稱,y是該實體的值。
      最后一個組件是fragment。盡管該組件作為URI的一部分出現(xiàn),但不是絕對的。當(dāng)使用URI進行某種檢索操作時,后面執(zhí)行操作的軟件使用fragment聚焦于軟件感興趣的資源部分(在該軟件成功檢索到資源的數(shù)據(jù)后)。
      為了實際表現(xiàn)前面提到的組件信息,可以使用下面的URI:
      ftp://george@x.com:90/public/notes?text=shakespeare#hamlet
      上面的URI把ftp識別為大綱,把george@x.com:90識別為基于服務(wù)器的授權(quán)機構(gòu)(其中g(shù)eorge是用戶信息,x.com是主機,90是端口),把/public/notes識別為路徑,把text=shakespeare識別為查詢,把hamlet識別為片斷。本質(zhì)上它是一個叫做george的用戶希望通過/public/notes路徑在服務(wù)器x.com的90端口上檢索shakespeare文本的hamlet信息。在shakespeare成功的返回到該程序后,程序定位hamlet段并把它呈獻給該用戶。
    標(biāo)準(zhǔn)化可以通過目錄術(shù)語來理解。假定目錄x直接位于根目錄之下,x有子目錄a和b,b有文件memo.txt,a是當(dāng)前目錄。為了顯示memo.txt中的內(nèi)容(在微軟Windows下),你可能輸入type \x\.\b\memo.txt。你也可能輸入type \x\a\..\b\memo.txt,在這種情況下,a和..的出現(xiàn)是沒有必要的。這兩種形式都不是最簡單的。但是如果輸入\x\b\memo.txt,你就指定了最簡單的路徑了,從根目錄開始訪問memo.txt。最簡單的\x\b\memo.txt路徑就是標(biāo)準(zhǔn)化的路徑。
      通常通過基本的和相對的URI訪問資源。基本的URI是絕對的URI,它唯一地標(biāo)識了某種資源的名字空間,而相對的URI標(biāo)識了與基礎(chǔ)的URI相對的資源。(與基本的URI不同,相對的URI在某種資源的生存周期內(nèi)可以永遠不需要改變)。因為基本的和相對的URI都不能完整的識別某種資源,有必要把兩種URI通過解析過程合并。相反地,通過相對化從合并的URI中提取相對的URI也是可行的。
      注意
      不透明的URI與其它的URI不同,它不服從標(biāo)準(zhǔn)化、分解和相對化。
      假定你把x://a/作為基礎(chǔ)的URI,并把b/c作為相對的URI。根據(jù)基礎(chǔ)URI分解這個相對的URI將產(chǎn)生x://a/b/c。根據(jù)x://a/相對化x://a/b/c將產(chǎn)生b/c。
      URI不能定位或讀取/寫入資源。這是統(tǒng)一的資源定位器(URL)的任務(wù)。URL是一種URI,但是它的大綱組件是已知的網(wǎng)絡(luò)協(xié)議(簡稱協(xié)議),并且它把URI組件與某種協(xié)議處理程序(一種資源定位器和根據(jù)協(xié)議建立的約束規(guī)則與資源通訊的讀/寫機制)。
      URI一般不能為資源提供持久不便的名稱。這是統(tǒng)一的資源命名(URN)的任務(wù)。URN也是一種URI,但是全球唯一的、持久不便的,即使資源不在存在或不再使用。
    使用URI
      網(wǎng)絡(luò)API通過提供了URI類(位于java.net程序包中),使我們在源代碼層使用URI成為可能。URI的構(gòu)造函數(shù)建立了封裝URI的URI對象;URI的方法建立URI對象;如果授權(quán)機構(gòu)組件是基于服務(wù)器的就分析它,提取URI組件,決定URI對象的URI是絕對的還是相對的;決定URI對象的URI是不透明的還是分層的;比較兩個URI對象中的URI;標(biāo)準(zhǔn)化(normalize)URI對象的URI;根據(jù)URI對象的基礎(chǔ)URI分解某個相對的URI以得到已分解的URI;根據(jù)URI對象的基礎(chǔ)URI關(guān)聯(lián)某個已分解的URI以得到相對的URI,把URI對象轉(zhuǎn)換為URL對象。
    我們進一步查看URI類,在它里面有五個構(gòu)造函數(shù)。最簡單的是URI(String uri)。這個構(gòu)造函數(shù)把URI作為String類型的參數(shù),把URI分解為組件,并把這些組件存儲在一個新的URI對象中。如果String對象的URI(通過uri引用)違反了RFC 2396的語法規(guī)則,其它的四個構(gòu)造函數(shù)URI(String uri)將會產(chǎn)生一個java.net.URISyntaxException對象。
      下面的代碼片斷演示了使用URI(String uri)建立封裝了一個簡單的URI組件的URI對象:
    URI uri = new URI ("
      典型情況下URI構(gòu)造函數(shù)用于建立封裝用戶指定的URI的URI對象。因為用戶可能輸入不正確的URI,所以URI構(gòu)造函數(shù)產(chǎn)生已檢查的URISyntaxException對象。這意味著你的代碼必須明確地嘗試著調(diào)用某個URI構(gòu)造函數(shù)并捕捉異常,或者通過在該方法的Throws子句中列舉URISyntaxException以"推卸責(zé)任"。
      如果你知道URI是有效的(例如在源代碼中的URI),將不會產(chǎn)生URISyntaxException對象。因為在這種情況下處理某個URI構(gòu)造函數(shù)的異常處理要求可能有困難,所以URI提供了靜態(tài)的create(String uri)方法。這個方法分解通過uri引用的String對象中包含URI,如果該URI沒有違反任何語法規(guī)則就建立URI對象(并從方法中返回對它的引用),否則將捕捉到一個內(nèi)部的URISyntaxException對象,把該對象包裝金一個未檢查的IllegalArgumentException對象中,并拋出這個IllegalArgumentException對象。因為IllegalArgumentException是未檢查的,你不需要明確的嘗試代碼并捕捉異常或把它的類名稱列舉在Throws子句中。
      下面的代碼片斷演示了create(String uri):
    URI uri = URI.create ("
      URI構(gòu)造函數(shù)和create(String uri)方法試圖分解出某個URI的授權(quán)機構(gòu)組件的用戶信息、主機和端口部分。對于按正常形式形成的基于服務(wù)器的授權(quán)機構(gòu)組件,它們是會成功的。對于按拙劣的形式形成的基于服務(wù)器的授權(quán)機構(gòu)組件,他們將會失敗--并且把該授權(quán)機構(gòu)組件當(dāng)作是基于注冊的。有時你可能知道某個URI的授權(quán)機構(gòu)組件必須是基于服務(wù)器的。你可以確保該URI的授權(quán)機構(gòu)組件分解出用戶信息、主機和端口,或者你可以確保將產(chǎn)生一個異常(伴隨著相應(yīng)的診斷信息)。你可以通過調(diào)用URI的parseServerAuthority()方法實現(xiàn)這種操作。如果成功分解出URI,該方法將返回包含提取的用戶信息、主機和端口部分的URI的新URI對象的一個引用(但是如果授權(quán)機構(gòu)組件已經(jīng)被分解過了,將會返回調(diào)用parseServerAuthority()的URI對象的引用。),否則該方法將產(chǎn)生一個URISyntaxException對象。
      下面的代碼片斷演示了parseServerAuthority():
    // 下面的parseServerAuthority()調(diào)用出現(xiàn)后會發(fā)生什么情況?
    URI uri = new URI ("http://foo:bar").parseServerAuthority();
     一旦擁有了URI對象,你就可以通過調(diào)用getAuthority()、getFragment()、getHost()、getPath()、getPort()、getQuery()、getScheme()、getSchemeSpecificPart()和 getUserInfo()方法提取多種組件。你也可以通過調(diào)用isAbsolute()確定該URI是絕對的還是相對的,通過調(diào)用isOpaque()確定該URI是不透明的還是分層的。如果返回值是true意味著該URI是絕對的或不透明的,如果返回值是false意味著該URI是相對的或分層的。
      列表1中的程序用命令行參數(shù)建立了一個URI對象,調(diào)用URI組件提取方法來檢索URI的組件,并調(diào)用URI的isAbsolute()和isOpaque()方法把該URI分類為絕對的/相對性和不透明的/分層的。
      列表1: URIDemo1.java
    // URIDemo1.java
    import java.net.*;
    class URIDemo1
    {
    public static void main (String [] args) throws Exception
    {
    if (args.length != 1)
    {
    System.err.println ("usage: java URIDemo1 uri");
    return;
    }
    URI uri = new URI (args [0]);
    System.out.println ("Authority = " +uri.getAuthority ());
    System.out.println ("Fragment = " +uri.getFragment ());
    System.out.println ("Host = " +uri.getHost ());
    System.out.println ("Path = " +uri.getPath ());
    System.out.println ("Port = " +uri.getPort ());
    System.out.println ("Query = " +uri.getQuery ());
    System.out.println ("Scheme = " +uri.getScheme ());
    System.out.println ("Scheme-specific part = " +
    uri.getSchemeSpecificPart ());
    System.out.println ("User Info = " +uri.getUserInfo ());
    System.out.println ("URI is absolute: " +uri.isAbsolute ());
    System.out.println ("URI is opaque: " +uri.isOpaque ());
    }
    }
      輸入java URIDemo1命令后,列表1的輸出結(jié)果如下:
    query://jeff@books.com:9000/public/manuals/appliances?stove#ge:
    Authority =
    jeff@books.com:9000
    Fragment = ge
    Host = books.com
    Path = /public/manuals/appliances
    Port = 9000
    Query = stove
    Scheme = query
    //jeff@books.com:9000/public/manuals/appliances?stove
    User Info = jeff
    URI is absolute: true
    URI is opaque: false
      上面的輸出顯示該URI是絕對的,因為它指定了一個大綱(query),并且該URI是分層的,因為query后面有/符號。
      技巧
      你應(yīng)該調(diào)用URI的compareTo(Object o)和equals(Object o)來決定URI的次序(為了排序目的)和等同性。你可以參考SDK文檔,查閱這些方法的更多信息。
    URI類支持基本的URI操作,包括標(biāo)準(zhǔn)化(normalization)、分解(resolution)和相對化(relativization)。標(biāo)準(zhǔn)化是通過URI的normalize()方法支持的。調(diào)用normalize()時,它返回對新URI對象的引用,該對象包含調(diào)用的URI對象的URI的標(biāo)準(zhǔn)的表現(xiàn)。
      列表2演示了normalize()方法。它把URI作為程序的唯一的參數(shù),URIDemo2打印出標(biāo)準(zhǔn)的相等的URI。
      列表2: URIDemo2.java
    // URIDemo2.java
    import java.net.*;
    class URIDemo2
    {
    public static void main (String [] args) throws Exception
    {
    if (args.length != 1)
    {
    System.err.println ("usage: java URIDemo2 uri");
    return;
    }
    URI uri = new URI (args [0]);
    System.out.println ("Normalized URI = " +
    uri.normalize ().toString ());
    }
    }?
      在編譯URIDemo2后,在命令行輸入java URIDemo2 x/y/../z/./q,將看到下面的輸出:
    Normalized URI = x/z/q
      上面的輸出顯示y、..和.消失了。這是因為..意味著你想直接在x下面訪問名字空間的z部分,.意味著你希望訪問與z部分相關(guān)的名字空間的q部分。
      URI通過提供resolve(String uri)、resolve(URI uri)和relativize(URI uri)方法支持反向解析和相對化操作。如果uri引用是空的(null)這三個方法都會產(chǎn)生NullPointerException對象。同樣,如果指定的URI違反了RFC 2396語法規(guī)則,resolve(String uri)通過的內(nèi)部的create(String uri)調(diào)用間接地產(chǎn)生一個IllegalArgumentException對象。
      列表3的代碼演示了resolve(String uri)和relativize(URI uri)。
      列表3: URIDemo3.java
    // URIDemo3.java
    import java.net.*;
    class URIDemo3
    {
    public static void main (String [] args) throws Exception
    {
    if (args.length != 2)
    {
    System.err.println ("usage: " +
    "java URIDemo3 uriBase uriRelative");
    return;
    }
    URI uriBase = new URI (args [0]);
    System.out.println ("Base URI = " +uriBase.toString ());
    URI uriRelative = new URI (args [1]);
    System.out.println ("Relative URI = " +uriRelative.toString ());
    URI uriResolved = uriBase.resolve (uriRelative);
    System.out.println ("Resolved URI = " +uriResolved.toString ());
    URI uriRelativized = uriBase.relativize (uriResolved);
    System.out.println ("Relativized URI = " +uriRelativized.toString ());
    }
    }
      在編譯URIDemo3后,在命令行輸入java URIDemo3 http://www.somedomain.com/ x/../y. ,輸出如下:
    Base URI = http://www.somedomain.com/
    Relative URI = x/../y
    Resolved URI = http://www.somedomain.com/y
    Relativized URI = y
      上面的輸出顯示相對的URI的x/../y根據(jù)基礎(chǔ)URI http://www.somedomain.com/分解并(在內(nèi)部)標(biāo)準(zhǔn)化,取得了已分解的http://www.somedomain.com/URI。給定該URI和基礎(chǔ)URI,該已分解的URI根據(jù)基礎(chǔ)URI相對化獲得了y,它是原始的但是標(biāo)準(zhǔn)的相對的URI。
      技巧
      調(diào)用URI的toURL()方法把URI轉(zhuǎn)換為URL。
      在本周日的專題中我將向讀者介紹如何使用URL以及MIME(多用途的網(wǎng)際郵件擴充協(xié)議)的概念以及它如何與URL發(fā)生聯(lián)系,敬請期待。
    posted on 2006-04-03 15:11 SIMONE 閱讀(576) 評論(0)  編輯  收藏 所屬分類: JAVA
    主站蜘蛛池模板: 亚洲av无码专区在线| 亚洲乱码国产一区网址| 亚洲色偷偷偷综合网| 亚洲欧洲国产精品香蕉网| 日本一区二区三区免费高清| 一级人做人a爰免费视频| 亚洲视频一区在线观看| 国产美女亚洲精品久久久综合| 91精品免费不卡在线观看| 精品一区二区三区高清免费观看 | 在线亚洲v日韩v| 久久精品国产亚洲精品2020| 精品国产香蕉伊思人在线在线亚洲一区二区 | AV激情亚洲男人的天堂国语| 亚洲高清在线mv| 亚洲国产成人久久综合一| 亚洲s色大片在线观看| 亚洲男女内射在线播放| 成人女人A级毛片免费软件| 男女作爱在线播放免费网站| 韩国免费A级毛片久久| 三根一起会坏掉的好痛免费三级全黄的视频在线观看 | 亚洲精品国产电影| 国产成人精品亚洲精品| 免费jjzz在线播放国产| 国产亚洲精品资在线| 亚洲av永久无码精品秋霞电影影院 | 精品久久久久亚洲| 美美女高清毛片视频黄的一免费 | 亚洲国产一二三精品无码| 久久久久亚洲AV成人无码 | 国产日韩在线视频免费播放| 四虎影视无码永久免费| 99久久久精品免费观看国产 | 亚洲精品国产suv一区88| 伊人久久国产免费观看视频| 亚洲精品tv久久久久久久久| 亚洲国产精品综合福利专区| 亚洲第一街区偷拍街拍| 精品无码AV无码免费专区| eeuss草民免费|