escape、encodeURI和encodeURIComponent的區別


1.簡單解釋

  簡單來說,escape是對字符串(string)進行編碼(而另外兩種是對URL),作用是讓它們在所有電腦上可讀。
  編碼之后的效果是%XX或者%uXXXX這種形式。
  其中 ASCII字母、數字、@*/+ ,這幾個字符不會被編碼,其余的都會。
  最關鍵的是,當你需要對URL編碼時,請忘記這個方法,這個方法是針對字符串使用的,不適用於URL。

2.   encodeURI和encodeURIComponent

  對URL編碼是常見的事,所以這兩個方法應該是實際中要特別注意的。
  它們都是編碼URL,唯一區別就是編碼的字符范圍,其中
  encodeURI方法不會對下列字符編碼 ASCII字母、數字、~!@#$&*()=:/,;?+'
  encodeURIComponent方法不會對下列字符編碼 ASCII字母、數字、~!*()'
也就是encodeURIComponent編碼的范圍更廣,會將http://XXX中的//也編碼,會導致URL不可用。(其實java中的URLEncoder.encode(str,char)也類似於這個方法,會導致URL不可用)

 

3簡單使用

3.1編碼中文

    var param = "中文";
    console.log(escape(param));
    console.log(encodeURI(param));
    console.log(encodeURIComponent(param));

 

結果:

 

3.2 encodeURI和encodeURIComponent編碼URL

    var url = "http://localhost:85/Exam/settingAction_saveSettings.action?safeHatNumLength=測試";
    console.log(encodeURI(url));
    console.log(encodeURIComponent(url));

 結果:

http://localhost:85/Exam/settingAction_saveSettings.action?safeHatNumLength=%E6%B5%8B%E8%AF%95
http%3A%2F%2Flocalhost%3A85%2FExam%2FsettingAction_saveSettings.action%3FsafeHatNumLength%3D%E6%B5%8B%E8%AF%95

 

4.使用場景 

1、如果只是編碼字符串,不和URL有半毛錢關系,那么用escape,而且這個方法一般不會用到。
2、如果你需要編碼整個URL,然后需要使用這個URL,那么用encodeURI。
3、當你需要編碼URL中的參數的時候,那么encodeURIComponent是最好方法。

 

5.測試URL傳中文參數問題

 此時tomcat的編碼是iso8859-1默認編碼,后台采用struts2的屬性驅動接受。並且進行解碼: (Java后台解碼)

        System.out.println(safeHatNumLength);
        try {
            System.out.println(URLDecoder.decode(safeHatNumLength,"UTF-8"));
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        }

 

5.1直接在url中輸入中文查看后台:

 http://localhost:85/Exam/settingAction_saveSettings.action?safeHatNumLength=測試

 

結果:

测è¯

 

原因:直接訪問瀏覽器會將中文采用utf-8編碼傳到后台,后台tomcat接收到之后采用iso8859-1解碼所以亂碼

5.2window.open不編碼直接訪問

    var url = "http://localhost:85/Exam/settingAction_saveSettings.action?safeHatNumLength=測試";
    window.open(encodeURI(url));

結果與原因同上同上

 

5.3   URL中文參數兩次編碼得到正確結果(一次編碼不能得到正確結果)

總結:參數攜帶中文需要兩次編碼,如下:

        var url = encodeURI(encodeURI("http://localhost:85/Exam/settingAction_saveSettings.do?safeHatNumLength=測試"));
        console.log(url);
        window.open(url);

結果:

%E6%B5%8B%E8%AF%95
測試

 

原因:兩次編碼傳到后台之后,tomcat收到參數第一次進行解碼之后變為一次utf-8編碼的字符串,所以再次調用解碼一次就變為中文。 

 

5.4  表單get方法提交一次編碼就可以

    <form id="testForm" action="/Exam/settingAction_saveSettings.do" method="get">
            <input name="safeHatNumLength" />
            <input type="button" value="提交" onclick="submitForm();" />
    </form>
    <script>
    function submitForm() {
        $.get("/Exam/settingAction_saveSettings.do",encodeURI($("#testForm").serialize()));
    }
</script>

 

后台結果::

%E9%97%AE%E9%97%AE
問問

 

總結:  

  如果只對參數編碼用encodeURIComponent編碼就可以,當然用 encodeURI也可以,如果不生效可以用兩次編碼。

  如果是對整個URL進行編碼最好用encodeURI,而且是兩次編碼 ,否則有可能不必生效。

  判斷是否生效只需要看帶到后台的參數是否是編碼后的格式,或者url的地址是否是編碼之后的。

補充:瀏覽器也可以查看默認編碼:

 

alert(document.charset)

 

 

 

 

關於兩次編碼的原因:

 假設參數是一個"中"字
1.第一次encodeURI,按照utf-8方式獲取字節數組變成[-28,-72-83],對字節碼數組進行遍歷,把每個字節轉化成對應的16進制數,這樣就變成了[E4,B8,AD],最后變成[%E4,%B8,%AD]

2.第二次encodeURI,把數組最后變成[%25E4,%25B8,%25AD]然后就把處理后的數據[%25E4,%25B8,%25AD]發往服務器端,

當應用服務器調用getParameter方法,getParameter方法會去向應用服務器請求參數,應用服務器最初獲得的就是發送來的[%25E4,%25B8,%25AD],

應用服務器會對這個數據進行URLdecode操作,URldecode操作和encodeURL操作是相反的操作,處理結果就是[%E4,%B8,%AD],並把這個值返回給getParameter方法,然后再在服務器端中調用相應的URL轉碼方法或者是函數  就可以把數據還原成最初頁面發送過來的中文“中”了。

 

URL編碼與兩次encodeURI

當使用地址欄提交查詢參數時,如果不編碼,非英文字符會按照操作系統的字符集進行編碼提交到服務器,服務器會按照配置的字符集進行解碼,所以如果兩者不一致就會導致亂碼。

encodeURI函數采用UTF-8對URL進行編碼,所以如果服務器在進行解碼時使用的是其他的編碼方式就會出現亂碼,默認的服務器配置的解碼字符集都不是UTF-8,所以大部分情況下地址欄提交中文查詢參數時會產生亂碼;針對這種情況,可以連續使用兩次encodeURI在客戶端(主要指瀏覽器)對非英文字符進行編碼,然后在服務端使用Java.NET.URLDecoder(String."UTF-8")解碼,即可得到正確的中文。

如果只進行一次encodeURI,得到的是UTF-8形式的URL,服務器端通過request.getParameter()解碼查詢參數(通常是iso-8859-1)就會得到亂碼。

如果進行兩次encodeURI,第一次編碼得到的是UTF-8形式的URL,第二次編碼得到的依然是UTF-8形式的URL,但是在效果上相當於首先進行了一次UTF-8編碼(此時已經全部轉換為ASCII字符),再進行了一次iso-8859-1編碼,因為對英文字符來說UTF-8編碼和ISO-8859-1編碼的效果相同。在服務器端,首先通過request.getParameter()自動進行第一次解碼(可能是gb2312,gbk,utf-8,iso-8859-1等字符集,對結果無影響)得到ascii字符,然后再使用UTF-8進行第二次解碼,通常使用java.net.URLDecoder("","UTF-8")方法。

兩次編碼兩次解碼的過程為:

UTF-8編碼->UTF-8(iso-8859-1)編碼->iso-8859-1解碼->UTF-8解碼,編碼和解碼的過程是對稱的,所以不會出現亂碼。(實際tomcat服務器收到參數之后就會進行一次解碼,也就是第一次解碼)

encodeURL函數主要是來對URI來做轉碼,它默認是采用的UTF-8的編碼.
. UTF-8編碼的格式:一個漢字來三個字節構成,每一個字節會轉換成16進制的編碼,同時添加上%號

 

1.首先前台測試編碼效果:(驗證上面的編碼效果)

(1)第一次編碼:

    console.log(encodeURI("中"));
    console.log(encodeURI(encodeURI("中")));

結果:

%E4%B8%AD
%25E4%25B8%25AD

 

2.下面進行后台Java接受演示

一個簡單的servlet代碼:

        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String string = (String) parameterNames.nextElement();
            log.info("key -> {},value -> {}", string, request.getParameter(string));
        }

 

(1)測試一次編碼,tomcat中編碼為iso8859-1(這種也無法進行解碼,已經發生亂碼)

直接URL中輸入:   http://localhost/index.html?param=中  

實際谷歌瀏覽器自動編碼為:http://localhost/index.html?param=%E4%B8%AD

 

查看看后台結果:

    2018-12-27 19:09:02 [cn.ding.test.TestServlet]-[INFO] key -> param,value -> 中

 

(2)測試一次編碼,tomcat中編碼為UTF-8(一次編碼后台正常接受到的就是正常的中文)

直接URL中輸入:   http://localhost/index.html?param=中  

實際谷歌瀏覽器自動編碼為:http://localhost/index.html?param=%E4%B8%AD

 

查看看后台結果:

    2018-12-27 19:13:55 [cn.ding.test.TestServlet]-[INFO] key -> param,value -> 中

 

(3)測試2次編碼,tomcat中編碼為iso8859-1

  直接URL中輸入:   http://localhost/index.html?param=%25E4%25B8%25AD

結果: (可以看出來tomcat解碼了一次)

  2018-12-27 19:16:12 [cn.ding.test.TestServlet]-[INFO] key -> param,value -> %E4%B8%AD

 

此時如果我們用下面方法可以將參數解析為正常的中文:

URLDecoder.decode("%E4%B8%AD", "utf-8")

 

(4)測試2次編碼,tomcat中編碼為utf-8

  直接URL中輸入:   http://localhost/index.html?param=%25E4%25B8%25AD

結果: (可以看出來tomcat解碼了一次)

  2018-12-27 19:19:10 [cn.ding.test.TestServlet]-[INFO] key -> param,value -> %E4%B8%AD

此時如果我們用下面方法可以將參數解析為正常的中文:

URLDecoder.decode("%E4%B8%AD", "utf-8")

 

  通過上面明白了,實際前台encodeURI編碼的次數與你后台默認的編碼格式相關,如果你的后台默認是UTF-8編碼,前台對中文只需要一次encodeURI即可;如果后台默認的是ios8859-1,一次編碼之后將造成亂碼無法還原,前台編碼兩次后台收到的解碼一次的效果,所以才有utf-8解碼一次即可還原。

  也就是你需要記住tomcat收到參數之后就會用server.xml中的編碼格式進行一次解碼,所以編碼解碼與次數問題就很好理解了。

 

補充:Tomcat編碼問題---------------實際上此編碼告訴tomcat以哪種編碼解析參數

tomcat8以后默認編碼格式是utf-8;7之前的都是iso8859-1

如果默認情況下,tomcat使用的的編碼方式:iso8859-1

修改tomcat下的conf/server.xml文件

找到如下代碼:    

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

這段代碼規定了Tomcat監聽HTTP請求的端口號等信息。

可以在這里添加一個屬性:URIEncoding,將該屬性值設置為UTF-8,即可讓Tomcat(默認ISO-8859-1編碼)以UTF-8的編碼處理get請求。

修改完成后:

<Connector port="8080"  protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM