這兩天在寫代碼的時候,由于涉及到資源的位置,是以,需要在java bean中定義一些字段,用來表示資源的位置,比如:imgurl,logouri等等。但是,每次定義的時候,心裡都很糾結,是該用imgurl還是imguri呢?
同樣的,另外一個問題:string httpservletrequest.getrequesturi();和stringbuffer httpservletrequest.getrequesturl();傳回的内容有何不同?為什麼會如此?
帶着這些問題到網上去搜了下,沒發現讓自己看了明白的解釋,于是,想到了java類庫裡有兩個對應的類java.net.uri和java.net.url,終于,在這兩個類裡的javadoc裡找到了答案。
uris, urls, and urns
首先,uri,是uniform resource identifier,統一資源辨別符,用來唯一的辨別一個資源。而url是uniform resource locator,統一資源定位器,它是一種具體的uri,即url可以用來辨別一個資源,而且還指明了如何locate這個資源。而urn,uniform resource name,統一資源命名,是通過名字來辨別資源,比如mailto:[email protected]。也就是說,uri是以一種抽象的,高層次概念定義統一資源辨別,而url和urn則是具體的資源辨別的方式。url和urn都是一種uri。
在java的uri中,一個uri執行個體可以代表絕對的,也可以是相對的,隻要它符合uri的文法規則。而url類則不僅符合語義,還包含了定位該資源的資訊,是以它不能是相對的,schema必須被指定。
ok,現在回答文章開頭提出的問題,到底是imgurl好呢,還是imguri好?顯然,如果說imguri是肯定沒問題的,因為即使它實際上是url,那它也是uri的一種。那麼用imgurl有沒有問題呢?此時則要看它的可能取值,如果是絕對路徑,能夠定位的,那麼用imgurl是沒問題的,而如果是相對路徑,那還是不要用imgurl的好。總之,用imguri是肯定沒問題的,而用imgurl則要視實際情況而定。
第二個,從httpservletrequest的javadoc中可以看出,getrequesturi傳回一個string,“the part of this request’s url from the protocol name up to the query string in the first line of the http request”,比如“post /some/path.html?a=b http/1.1”,則傳回的值為”/some/path.html”。現在可以明白為什麼是getrequesturi而不是getrequesturl了,因為此處傳回的是相對的路徑。而getrequesturl傳回一個stringbuffer,“the returned url contains a protocol, server name, port number, and server path, but it does not include query string parameters.”,完整的請求資源路徑,不包括querystring。
總結一下:url是一種具體的uri,它不僅唯一辨別資源,而且還提供了定位該資源的資訊。uri是一種語義上的抽象概念,可以是絕對的,也可以是相對的,而url則必須提供足夠的資訊來定位,是以,是絕對的,而通常說的relative url,則是針對另一個absolute url,本質上還是絕對的。
注:這裡的絕對(absolute)是指包含scheme,而相對(relative)則不包含scheme。
uri抽象結構 [scheme:]scheme-specific-part[#fragment]
[scheme:][//authority][path][?query][#fragment]
authority為[user-info@]host[:port]
參考資料:
<a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/net/uri.html">http://docs.oracle.com/javase/1.5.0/docs/api/java/net/uri.html</a>
<a href="http://en.wikipedia.org/wiki/uniform_resource_identifier">http://en.wikipedia.org/wiki/uniform_resource_identifier</a>
<a href="http://docs.oracle.com/javaee/5/api/javax/servlet/http/httpservletrequest.html">http://docs.oracle.com/javaee/5/api/javax/servlet/http/httpservletrequest.html</a>
ps:
java.net.url類不提供對标準rfc2396規定的特殊字元的轉義,是以需要調用者自己對url各組成部分進行encode。而java.net.uri則會提供轉義功能。是以the recommended way to manage the encoding and decoding of urls is to use java.net.uri. 可以使用uri.tourl()和url.touri()方法來對兩個類型的對象互相轉換。對于html form的url encode/decode可以使用java.net.urlencoder和java.net.urldecoder來完成,但是對url對象不适用。