空格URL編碼的正確使用姿式

一、簡介

       空格目前有兩種不一樣的編碼方式,一種是在HTML4中定義的,而另外一種是在RFC-3986中定義的。本文將簡要介紹這兩種編碼方式,以及會給咱們的開發工做帶來什麼樣的問題,最後給出一些編碼建議。html

1.1 HTML4編碼方式

        HTML4的application/x-www-form-urlencoded一節對空格的編碼定義以下:java

  1. Control names and values are escaped. Space characters are replaced by `+', and then reserved characters are escaped as described in [RFC1738], section 2.2: Non-alphanumeric characters are replaced by `%HH', a percent sign and two hexadecimal digits representing the ASCII code of the character. Line breaks are represented as "CR LF" pairs (i.e., `%0D%0A').git

  2. The control names/values are listed in the order they appear in the document. The name is separated from the value by `=' and name/value pairs are separated from each other by `&'.數據庫

    按照HTML4規範,空格應該被編碼成加號"+",而若是字符自己就是加號"+",則應該被編碼成%2B。apache

 1.2 RFC-3986編碼方式

     RFC-3986中採用統一的編碼方式,字符的編碼格式爲:%HH(H爲十六進制字符), 並無對空格作特殊處理。按照RFC-3986規範,空格被編碼成%20,而加號"+"被編碼成%2B。api

1.3 致使的問題

    從上面能夠看出,空格在兩種規範下有不一樣的編碼方式,也所以致使咱們在開發時會遇到意想不到的錯誤。例如用戶明明提交的是"你 好",寫入數據庫以後卻變成了"你+好",每每這種錯誤讓人摸不着頭腦,其實這就是因爲空格的編碼錯誤致使的。app

2. 編碼建議

    其實避免上面錯誤的方法很簡單,就是在開發中咱們要統一客戶端和服務端的編碼方式,而不能二者混用。建議客戶端和服務端同時使用RFC-3986編碼方式,將請求參數所有編碼成%HH格式。固然爲了保證正確的編碼解碼,統一的字符集也不可缺乏,最好都使用UTF-8。編碼

3. 編碼示例

    若是客戶端提交的查詢字符串是"開源+中國 博客", 則HTML4採用UTF-8編碼後結果爲:url

%E5%BC%80%E6%BA%90%2B%E4%B8%AD%E5%9B%BD+%E5%8D%9A%E5%AE%A2

    注意,加號被直接編碼成%2B,而空格則被編碼成了加號"+"。spa

  而RFC-3986採用UTF-8編碼後結果爲:

%E5%BC%80%E6%BA%90%2B%E4%B8%AD%E5%9B%BD%20%E5%8D%9A%E5%AE%A2

    加號被直接編碼成%2B,空格也被直接編碼成%20。

4. Java中的URL編碼

    Java中經常使用的URL編碼類有兩個:一個是JDK自帶的java.net.URLEncoder,另外一個是Apache的org.apache.commons.codec.net.URLCodec。這兩個類遵循的都是HTML4標準,即將空格編碼成加號"+",代碼以下:

//輸出:%E4%BD%A0+%E5%A5%BD
System.out.println(java.net.URLEncoder.encode("你 好", "utf-8"));
URLCodec en = new URLCodec("utf-8");
//輸出:%E4%BD%A0+%E5%A5%BD
System.out.println(en.encode("你 好"));

   其實要將HTML4的編碼結果轉換成RFC-3986編碼,方法很簡單:

java.net.URLEncoder.encode("你 好", "utf-8").replaceAll("\\+", "%20");

   另外Netty中有一個QueryStringEncoder類能夠能夠實現RFC-3986URL編碼,代碼以下:

QueryStringEncoder encoder = new QueryStringEncoder("/");
encoder.addParam("name", "開源+中國 博客");
//輸出:/?name=%E5%BC%80%E6%BA%90%2B%E4%B8%AD%E5%9B%BD%20%E5%8D%9A%E5%AE%A2
System.out.println(encoder.toUri());

5. 參考

URI Escaping and java.net.URLEncoder

相關文章
相關標籤/搜索