Java 創立URL的罕見成績及處理計劃。本站提示廣大學習愛好者:(Java 創立URL的罕見成績及處理計劃)文章只能為提供參考,不一定能成為您想要的結果。以下是Java 創立URL的罕見成績及處理計劃正文
URL無處不在,不外仿佛開辟人員並沒有真正地輿解它們,由於我在Stack Overflow上常常看到有人在問若何准確的創立一個URL。想曉得URL語法是若何任務的,可以看下Lunatech的 這篇文章 ,異常不錯 。
本文不會深刻引見URL的全體語法(假如你想周全懂得URL的話,可以讀下 RFC 3986 , RFC 1738 , 和下面提到的那篇文章,還有 W3下面的文檔 ), 這裡我想講的是罕見的一些庫在操作URL方面存在的毛病,和若何經由過程 URL-builder 來准確的應用它,這是我們宣布的一個用於准確地創立URL的Java庫。
成績1:Java的URLEncoder
這個類不只名字取的很差,並且它的文檔下去第一句話就不太仇人。
Utility class for HTML form encoding.
你能夠正疑惑為何叫URLEncoder呢,看到這行就完全無語了。
假如你讀過Lunatech的那篇博文,如今你應當明確了,你沒法經由過程這個類將一個URL串事業般地轉化成一個平安,准確編碼的URL對象,固然假如你沒做足作業的話,這裡有個小例子可以贊助你懂得下。
假定你有個HTTP的辦事端點http://foo.com/search,它接收一個查詢參數p,p的值就是要查找的字符串。假如你搜刮”You & I”這個串的話,你第一次創立的搜刮的URL能夠是如許:http://foo.com/search?q=You & I。這個固然沒法任務,由於&是分隔查詢參數name/value對的分隔符。假如你拿到這個紊亂的URL串的話,你對它的確一籌莫展,由於起首你就沒法准確的解析它。
那好,我們來應用下URLEncoder。URLEncoder.encode(“You & I”, “UTF-8″)是成果是You+%26+I。這個%26解碼以後就是&,而+號在查詢串中代表的就是空格,是以這個URL是能正常任務的。
如今假定你想應用你的查詢串來拼接URL途徑,而不是放到URL參數外面。很顯著,http://foo.com/search/You & I是毛病的。不幸的是,URLEncoder.encode()的成果也是錯的。http://foo.com/search/You+%26+I解碼後會獲得/search/You+&+I,由於+號在URL途徑中是不會解析成空格的。
URLEncoder也許能知足你的一些場景。但不幸的是,它這個過於通用的名字使得開辟人員很輕易誤用它。是以最好的辦法就是不要應用它,省得前面其余開辟人員在你的基本上又應用了其余功效時出錯(除非,你真的是在停止”HTML表單編碼”)。
成績2:Groovy HttpBuilder和Java的URI
HTTP Builder 是Groovy的一個HTTP客戶端庫。
創立一個通俗的GET要求異常簡略:
new HTTPBuilder("http://localhost:18080").request(Method.GET) { uri.path = "/foo" }
這段代碼會發送GET /foo HTTP/1.1到辦事端(你可以運轉nc -l -p 18080以後再履行這段代碼驗證下)。
我們來試一下包括空格的URL。
new HTTPBuilder("http://localhost:18080").request(Method.GET) { uri.path = "/foo bar" }
這個發送的是GET /foo%20bar HTTP/1.1,看起來還不錯。
如今假定我們的途徑中有一段就叫做foo/bar。這可不克不及簡略地發送foo/bar就完了,由於這會被以為成途徑中包括兩段,foo和bar,那我們試下foo%2Fbar吧(把/調換成對應的編碼)。
new HTTPBuilder('http://localhost:18080').request(Method.GET) { uri.path = '/foo%2Fbar' }
這個發送的則是GET /foo%252Fbar HTTP/1.1。這可不太妙。%2F中的%被反復編碼了,如許解碼後拿到的途徑是foo%2Fbar而不是foo/bar。這裡其實真正要怪的是 java.net.URI,由於這個HTTPBuilder裡的URIBuilder類用的就是它。
上述代碼中的設置裝備擺設閉包中裸露的uri屬性的類型是URIBuilder。假如你經由過程uri.path = …來更新uri的path屬性的話,它終究會挪用URI的一個結構辦法,這個辦法關於傳入的path屬性是這麼描寫的:
假如供給了path參數,則將它追加到URL前面。path外面的字符,只需不長短保存,標點,本義及其它分類(譯注:這幾個分類在RFC 2396中有具體解釋)的字符,同時又不是/或許@號的,都邑停止編碼。
這個做法意義不年夜,由於假如未編碼前的文本包括特別字符的話,它就沒法生成一個准確編碼的途徑分段。換句話說,“我會對這個字符串停止編碼,而編碼以後它就是准確的”,這固然是個謬論,而URI正好是這個謬論的就義品。假如字符串曾經准確編碼了,那就沒甚麼成績,假如不是的話,那就垮台了,由於這個串沒法解析。現實上,文檔裡說的不會對/號本義的意思是,它假定path串曾經准確地編碼了(就是說准確地應用/來分隔途徑),同時又還沒有准確地編碼(除/外的其它部門依然須要停止編碼)。
假如HTTPBuilder不應用URI類的這個存在缺點的功效就行了,固然了,假如URI本身自己沒成績的話就更好了。
准確的做法
我們寫了這個url-builder,它能贊助開辟人員便利的拼接各類類型的URL。它遵守了篇首那幾個參考材料中的編碼標准,同時它還供給了流式的API。上面這個應用示例簡直可以涵蓋一切的應用場景了:
UrlBuilder.forHost("http", "foo.com") .pathSegment("with spaces") .pathSegments("path", "with", "varArgs") .pathSegment("&=?/") .queryParam("fancy + name", "fancy?=value") .matrixParam("matrix", "param?") .fragment("#?=") .toUrlString()
成果是: http://foo.com/with%20spaces/path/with/varArgs/&=%3F%2F;matrix=param%3F?fancy%20%2B%20name=fancy?%3Dvalue#%23?=
這個例子演示了URL各個部門的分歧的編碼規矩,好比說在途徑中未編碼的&=是許可的,而?/則是須要編碼的,但在查詢參數中=是須要編碼的,但?號則不須要,由於這裡曾經是查詢串的部門了(譯注:查詢串是從一個?號開端的,是以前面可以包括?號)。
感激浏覽,願望能贊助到年夜家,感謝年夜家對本站的支撐!