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

    圖1:
    ?
    URI、URL和URN之間的層次關系。URL和URN是URI的子范疇。
      URI表示的是統一的資源標識,它是以某種統一的(標準化的)方式標識資源的簡單字符串。典型情況下,這種字符串以scheme(命名URI的名字空間的標識符--一組相關的名稱)開頭,語法如下:
      [scheme:] scheme-specific-part
      URI以scheme和冒號開頭。Scheme用大寫/小寫字母開頭,后面為空或者跟著更多的大寫/小寫字母、數字、加號、減號和點號。冒號把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看作是以某種方式引用某種資源,而這種方式對標識符出現的環境沒有依賴。如果使用文件系統作類比,絕對的URI類似于從根目錄開始的某個文件的路徑。與絕對的URI不同的,相對的URI不是以scheme(后面跟著冒號)開始的URI。它的一個例子是articles/articles.html。你可以把相對的URI看作是以某種方式引用某種資源,而這種方式依賴于標識符出現的環境。如果用文件系統作類比,相對的URI類似于從當前目錄開始的文件路徑。
    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標識組件的普通子集的scheme-specific-part符合下面的語法:
      [//authority] [path] [?query] [#fragment]
      可選的authority組件標識了該URI名字空間的命名機構。如果有這一部分,它就是以一對正斜杠開始的,它可以是基于服務器或基于注冊的,并且它以后面的正斜杠、問號或沒有其它符號結束。基于注冊的授權機構組件有特定大綱的語法(本文沒有討論,因為很少使用它),而基于服務器的授權機構組件的語法如下:
      [userinfo@] host [:port]
      按照這種語法,基于服務器的授權機構組件可以隨意的以用戶信息(例如用戶名)開始,后面跟著一個@符號,緊接著是主機的名稱,以及冒號和端口號。例如jeff@x.com:90就是一個基于服務器的授權機構組件,其中jeff包含了用戶信息,x.com包含了主機,90包含了端口。
      可選的path組件根據授權機構組件(如果提供了)或大綱(如果沒有授權機構組件)識別資源的定位(或位置)。路徑(path)可以分成一系列的路徑片斷(path segment),每個路徑片斷使用正斜杠與其它的路徑片斷隔開。如果路徑的第一個路徑片斷以一個正斜杠開始,該路徑就被認為是絕對的。否則路徑就被認為是相對的。例如,/a/b/c由三個路徑片斷--a、b和c組成了一個路徑,此外,這個路徑是絕對的,因為第一個路徑片斷(a)的前綴是正斜杠。
      可選的query組件識別要傳遞給某種資源的數據。這種資源使用該數據獲取或生成其它的傳遞回調用者的數據。例如,http://www.somesite.net/a?x=y, x=y就是一個查詢(query),在這個查詢中,x=y是傳遞給某種資源的數據--x是某種實體的名稱,y是該實體的值。
      最后一個組件是fragment。盡管該組件作為URI的一部分出現,但不是絕對的。當使用URI進行某種檢索操作時,后面執行操作的軟件使用fragment聚焦于軟件感興趣的資源部分(在該軟件成功檢索到資源的數據后)。
      為了實際表現前面提到的組件信息,可以使用下面的URI:
      ftp://george@x.com:90/public/notes?text=shakespeare#hamlet
      上面的URI把ftp識別為大綱,把george@x.com:90識別為基于服務器的授權機構(其中george是用戶信息,x.com是主機,90是端口),把/public/notes識別為路徑,把text=shakespeare識別為查詢,把hamlet識別為片斷。本質上它是一個叫做george的用戶希望通過/public/notes路徑在服務器x.com的90端口上檢索shakespeare文本的hamlet信息。在shakespeare成功的返回到該程序后,程序定位hamlet段并把它呈獻給該用戶。
    標準化可以通過目錄術語來理解。假定目錄x直接位于根目錄之下,x有子目錄a和b,b有文件memo.txt,a是當前目錄。為了顯示memo.txt中的內容(在微軟Windows下),你可能輸入type \x\.\b\memo.txt。你也可能輸入type \x\a\..\b\memo.txt,在這種情況下,a和..的出現是沒有必要的。這兩種形式都不是最簡單的。但是如果輸入\x\b\memo.txt,你就指定了最簡單的路徑了,從根目錄開始訪問memo.txt。最簡單的\x\b\memo.txt路徑就是標準化的路徑。
      通常通過基本的和相對的URI訪問資源。基本的URI是絕對的URI,它唯一地標識了某種資源的名字空間,而相對的URI標識了與基礎的URI相對的資源。(與基本的URI不同,相對的URI在某種資源的生存周期內可以永遠不需要改變)。因為基本的和相對的URI都不能完整的識別某種資源,有必要把兩種URI通過解析過程合并。相反地,通過相對化從合并的URI中提取相對的URI也是可行的。
      注意
      不透明的URI與其它的URI不同,它不服從標準化、分解和相對化。
      假定你把x://a/作為基礎的URI,并把b/c作為相對的URI。根據基礎URI分解這個相對的URI將產生x://a/b/c。根據x://a/相對化x://a/b/c將產生b/c。
      URI不能定位或讀取/寫入資源。這是統一的資源定位器(URL)的任務。URL是一種URI,但是它的大綱組件是已知的網絡協議(簡稱協議),并且它把URI組件與某種協議處理程序(一種資源定位器和根據協議建立的約束規則與資源通訊的讀/寫機制)。
      URI一般不能為資源提供持久不便的名稱。這是統一的資源命名(URN)的任務。URN也是一種URI,但是全球唯一的、持久不便的,即使資源不在存在或不再使用。
    使用URI
      網絡API通過提供了URI類(位于java.net程序包中),使我們在源代碼層使用URI成為可能。URI的構造函數建立了封裝URI的URI對象;URI的方法建立URI對象;如果授權機構組件是基于服務器的就分析它,提取URI組件,決定URI對象的URI是絕對的還是相對的;決定URI對象的URI是不透明的還是分層的;比較兩個URI對象中的URI;標準化(normalize)URI對象的URI;根據URI對象的基礎URI分解某個相對的URI以得到已分解的URI;根據URI對象的基礎URI關聯某個已分解的URI以得到相對的URI,把URI對象轉換為URL對象。
    我們進一步查看URI類,在它里面有五個構造函數。最簡單的是URI(String uri)。這個構造函數把URI作為String類型的參數,把URI分解為組件,并把這些組件存儲在一個新的URI對象中。如果String對象的URI(通過uri引用)違反了RFC 2396的語法規則,其它的四個構造函數URI(String uri)將會產生一個java.net.URISyntaxException對象。
      下面的代碼片斷演示了使用URI(String uri)建立封裝了一個簡單的URI組件的URI對象:
    URI uri = new URI ("
      典型情況下URI構造函數用于建立封裝用戶指定的URI的URI對象。因為用戶可能輸入不正確的URI,所以URI構造函數產生已檢查的URISyntaxException對象。這意味著你的代碼必須明確地嘗試著調用某個URI構造函數并捕捉異常,或者通過在該方法的Throws子句中列舉URISyntaxException以"推卸責任"。
      如果你知道URI是有效的(例如在源代碼中的URI),將不會產生URISyntaxException對象。因為在這種情況下處理某個URI構造函數的異常處理要求可能有困難,所以URI提供了靜態的create(String uri)方法。這個方法分解通過uri引用的String對象中包含URI,如果該URI沒有違反任何語法規則就建立URI對象(并從方法中返回對它的引用),否則將捕捉到一個內部的URISyntaxException對象,把該對象包裝金一個未檢查的IllegalArgumentException對象中,并拋出這個IllegalArgumentException對象。因為IllegalArgumentException是未檢查的,你不需要明確的嘗試代碼并捕捉異常或把它的類名稱列舉在Throws子句中。
      下面的代碼片斷演示了create(String uri):
    URI uri = URI.create ("
      URI構造函數和create(String uri)方法試圖分解出某個URI的授權機構組件的用戶信息、主機和端口部分。對于按正常形式形成的基于服務器的授權機構組件,它們是會成功的。對于按拙劣的形式形成的基于服務器的授權機構組件,他們將會失敗--并且把該授權機構組件當作是基于注冊的。有時你可能知道某個URI的授權機構組件必須是基于服務器的。你可以確保該URI的授權機構組件分解出用戶信息、主機和端口,或者你可以確保將產生一個異常(伴隨著相應的診斷信息)。你可以通過調用URI的parseServerAuthority()方法實現這種操作。如果成功分解出URI,該方法將返回包含提取的用戶信息、主機和端口部分的URI的新URI對象的一個引用(但是如果授權機構組件已經被分解過了,將會返回調用parseServerAuthority()的URI對象的引用。),否則該方法將產生一個URISyntaxException對象。
      下面的代碼片斷演示了parseServerAuthority():
    // 下面的parseServerAuthority()調用出現后會發生什么情況?
    URI uri = new URI ("http://foo:bar").parseServerAuthority();
     一旦擁有了URI對象,你就可以通過調用getAuthority()、getFragment()、getHost()、getPath()、getPort()、getQuery()、getScheme()、getSchemeSpecificPart()和 getUserInfo()方法提取多種組件。你也可以通過調用isAbsolute()確定該URI是絕對的還是相對的,通過調用isOpaque()確定該URI是不透明的還是分層的。如果返回值是true意味著該URI是絕對的或不透明的,如果返回值是false意味著該URI是相對的或分層的。
      列表1中的程序用命令行參數建立了一個URI對象,調用URI組件提取方法來檢索URI的組件,并調用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的輸出結果如下:
    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后面有/符號。
      技巧
      你應該調用URI的compareTo(Object o)和equals(Object o)來決定URI的次序(為了排序目的)和等同性。你可以參考SDK文檔,查閱這些方法的更多信息。
    URI類支持基本的URI操作,包括標準化(normalization)、分解(resolution)和相對化(relativization)。標準化是通過URI的normalize()方法支持的。調用normalize()時,它返回對新URI對象的引用,該對象包含調用的URI對象的URI的標準的表現。
      列表2演示了normalize()方法。它把URI作為程序的唯一的參數,URIDemo2打印出標準的相等的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部分相關的名字空間的q部分。
      URI通過提供resolve(String uri)、resolve(URI uri)和relativize(URI uri)方法支持反向解析和相對化操作。如果uri引用是空的(null)這三個方法都會產生NullPointerException對象。同樣,如果指定的URI違反了RFC 2396語法規則,resolve(String uri)通過的內部的create(String uri)調用間接地產生一個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根據基礎URI http://www.somedomain.com/分解并(在內部)標準化,取得了已分解的http://www.somedomain.com/URI。給定該URI和基礎URI,該已分解的URI根據基礎URI相對化獲得了y,它是原始的但是標準的相對的URI。
      技巧
      調用URI的toURL()方法把URI轉換為URL。
      在本周日的專題中我將向讀者介紹如何使用URL以及MIME(多用途的網際郵件擴充協議)的概念以及它如何與URL發生聯系,敬請期待。
    posted on 2006-04-03 15:11 SIMONE 閱讀(576) 評論(0)  編輯  收藏 所屬分類: JAVA
    主站蜘蛛池模板: 免费在线观看日韩| 国产男女猛烈无遮档免费视频网站| 久青草国产免费观看| jizz日本免费| 和日本免费不卡在线v| 在线观看亚洲免费| 亚洲精选在线观看| 亚洲一卡2卡3卡4卡5卡6卡| 色噜噜狠狠色综合免费视频| 国产情侣久久久久aⅴ免费| 歪歪漫画在线观看官网免费阅读| 亚洲精品视频久久久| 亚洲精品动漫在线| 中文字幕无码免费久久9一区9| 99在线精品免费视频九九视| 亚洲午夜爱爱香蕉片| 中文字幕亚洲精品无码| 免费看搞黄视频网站| 亚洲啪啪免费视频| 日本高清不卡aⅴ免费网站| mm1313亚洲国产精品美女| 亚洲短视频在线观看| 成人人观看的免费毛片| 亚洲A∨无码无在线观看| 国产亚洲精品免费| 成人免费视频一区| 亚洲午夜久久久久久尤物| 国产在线国偷精品产拍免费| 亚洲第一区香蕉_国产a| 桃子视频在线观看高清免费完整| 亚洲精品无码久久久久A片苍井空| 日韩午夜理论免费TV影院| 精品亚洲视频在线观看| 精品一区二区三区无码免费直播 | 久久亚洲精品成人| 无人在线观看完整免费版视频| 老湿机一区午夜精品免费福利| 久久精品国产亚洲av四虎| 国产免费人成视频尤勿视频| 亚洲国模精品一区| 国产成人免费在线|