JSP編碼以及亂碼解決總結 .

轉自:http://blog.csdn.net/magister_feng/article/details/6616326

首先,說說JSP/Servlet中的幾個編碼的作用:

1.<%@pagepageEncoding="UTF-8" %>作用:

* 告訴JSP編譯器在將JSP文件編譯成Servlet時使用的編碼。通常,在JSP內部定義的字符串(直接在JSP中定義,而不是從瀏覽器提交的數據)出現亂碼時,很多都是由於該參數設置錯誤引起的。

例如,你的JSP文件是以GBK爲編碼保存的 (右擊jsp-->Properties --> Text file encoding設置成與pageEncoding不一致時,就有亂碼),而在JSP中卻指定pageEncoding="UTF-8",就會引起JSP內部定義的字符串爲亂碼。

* 當JSP中不指定contentType參數,也不使用response.setCharacterEncoding方法時,指定對服務器響應進行重新編碼的編碼

2.<%@pagecontentType="text/html;charset=GBK" %>response.setCharacterEncoding("UTF-8")作用:

* 指定對服務器響應進行重新編碼的編碼,服務器在將數據發送到瀏覽器前,對數據進行重新編碼。

 * 瀏覽器也是根據這個參數來對其接收到的數據進行解碼,對其發送的請求參數進行編碼(如果參數有:<%=URLEncoder.encode("測試","GBK") %>或javascript:encodeURI("測試")則以後者爲準),

自己可以在IE的菜單中選擇:查看(V) --> 編碼(D)查看得知瀏覽器的編碼(解碼)和<%@page contentType="text/html;charset=GBK" %>  response.setCharacterEncoding("UTF-8")設置的編碼是一致的。

因此:只要響應結果不是亂碼,則瀏覽器顯示結果一定不會是亂碼(服務器對響應編碼和瀏覽器對響應解碼的編碼是一樣的)。出現亂碼的情況是:瀏覽器編碼 ---> 服務器解碼得到的結果是亂碼 ---> 造成響應有亂碼 --> 瀏覽器顯示亂碼

3.<metahttp-equiv="Content-Type" content="text/html;charset=UTF-8">作用:

* 控制瀏覽器的以何種編碼顯示網頁的內容

* 與2中page指令設置的區別是,meta設置的是瀏覽器解釋,page設置的是服務端解釋

4.request.setCharacterEncoding("charset")作用:

* 設置對客戶端請求參數進行解碼所使用的編碼.

* 只對兩種請求參數提交方式有效:

* POST表單提交

* GET提交(url或GET表單提交), 此時要求配置

server.xml的<Connector>標籤的屬性:useBodyEncodingForURI="true"

5.request.getParameter("param")和request.getParameterValues("param")

所獲取到的參數數據都是經過服務器解碼後的數據

 

接着說下發送請求到返回響應整個編碼解碼過程:

1.瀏覽器對請求編碼--> 服務器(容器)對請求解碼 ---> 服務器對響應編碼 ---> 瀏覽器對響應解碼

瀏覽器編碼 ---> 容器解碼

瀏覽器編碼默認是使用response.setCharacterEncoding—contentType—pageEncoding的優先順序指定的編碼的,但當對某些參數使用<%=URLEncoder.encode("測試","GBK") %>或javascript:encodeURI("測試")來對參數編碼時,會覆蓋默認編碼,即瀏覽器這些特定的參數編碼以<%=URLEncoder.encode("測試","GBK") %>或javascript:encodeURI("測試")爲準

注意:javascript的編碼方式:encodeURI(..)和encodeURIComponent(..)是對其參數進行UTF-8編碼的

2.瀏覽器最終顯示響應結果出現亂碼是因爲在過程:

瀏覽器對請求編碼 --> 服務器(容器)對請求解碼,出現亂碼。

原因是:服務器對響應編碼和瀏覽器對響應解碼所使用的編碼都是相同的,爲response.setCharacterEncoding—contentType指定的編碼,而瀏覽器對請求參數的編碼 和 服務器對請求參數解碼 所使用的編碼如果不一致,就會造成亂碼

3.對中文解碼,無論使用什麼解碼方式都是中文。中文只有經過編碼,再解碼纔會出現亂碼的可能,如果起始編碼和末尾解碼所使用的編碼一致,就不會出現亂碼

4.瀏覽器編解碼說明:

瀏覽器在接收或發送數據時,會對URL和參數會進行URL解碼(接收)或編碼(發送),所使用的編碼爲:<%@pagecontentType="text/html;charset=GBK" %>或response.setCharacterEncoding("UTF-8")指定的編碼

5.服務器編解碼說明:

* 服務器發送數據時,按照response.setCharacterEncoding—contentType—pageEncoding的優先順序,對要發送的數據進行編碼。

* 服務器接收數據,要分三種情況。一種是瀏覽器直接用URL提交的數據,另外兩種是用表單的GET和POST方式提交的數據

(1)表單中POST方式提交的情況:

可以通過request.setCharacterEncoding(charset),來設置對瀏覽器提交的數據使用什麼樣的編碼進行解碼。如果不設置時,服務器默認使用ISO-8859-1來解碼請求參數。如果頁面的contentType="GBK", 此時要想得到正確的結果,則:

Stringname = newString(request.getParameter("name").getBytes("ISO-8859-1"),"GBK");

如果設置:request.setCharacterEncoding("GBK"),則只需:String name = request .getParameter("name");

所以對於POST表單提交的數據,在獲得數據的JSP頁面中request.setCharacterEncoding要和生成提交該表單的JSP頁面的response.setCharacterEncoding設置成相同的值。還有一種方法解決POST提交亂碼問題:使用過濾器,在過濾器中設置request.setCharacterEncoding(charset)

(2)URL提交的數據和表單中GET方式提交的情況:

此時設置request.setCharacterEncoding參數是不行的,因爲在Tomcat5.0中,默認情況下使用ISO-8859-1對URL提交的數據和表單中GET方式提交的數據進行解碼,而不使用該參數對URL提交的數據和表單中GET方式提交的數據解碼。要解決該問題,應該在Tomcat的配置文件server.xml的Connector標籤中設置useBodyEncodingForURI或者URIEncoding屬性,

*useBodyEncodingForURI參數爲true時表示用request.setCharacterEncoding參數對URL提交的數據和表單中GET方式提交的數據進行重新解碼。

*URIEncoding參數指定對所有GET方式請求(包括URL提交的數據和表單中GET方式提交的數據)進行統一解碼的編碼

即處理get方式請求參數有四種情況:

* 不設置server.xml的Connector標籤,此時服務器統一對get方式的請求參數進行ISO-8859-1解碼,此時設置request.setCharacterEncoding(charset)是無效的

* 設置server.xml的Connector標籤,令useBodyEncodingForURI="true",此時使用情況和post提交方式一致

* 設置server.xml的Connector標籤,令URIEncoding="charset",此時服務器統一對get方式的請求參數進行charset解碼

* 設置server.xml的Connector標籤,令useBodyEncodingForURI="true"URIEncoding="charset", 此時URIEncoding設置無效

 

<Connectorport="8080" maxThreads="150" minSpareThreads="25"maxSpareThreads="75" enableLookups="false"

redirectPort="8443"acceptCount="100" debug="0"connectionTimeout="20000" disableUploadTimeout="true"

useBodyEncodingForURI="true"URIEncoding="UTF-8"/>

 

範例:URLDecoder.decode(..)是服務器端解碼的,而encodeURI(..)是js在客戶端編碼的

1. javascrip對於get方式的參數編碼: Java代碼:url=encodeURI(url);服務器端獲取參數後解碼: Java代碼

Stringlinename = newString(request.getParameter("name").getBytes("ISO-8859-1"),"UTF-8");

說明:此時並沒有對server.xml的<Connector>配置useBodyEncodingForURI和URIEncoding屬性

編碼過程:瀏覽器編碼(UTF-8)--> 服務器解碼(ISO-8859-1) --> String.getBytes方法編碼(ISO-8859-1)--> 創建String解碼(UTF-8)

2.javascript:url=encodeURI(encodeURI(url)); //用了2次encodeURI服務器端獲取: Java代碼

Stringlinename = request.getParameter(name); //java : 字符解碼linename =java.net.URLDecoder.decode(linename , "UTF-8");

瀏覽器編碼(UTF-8) --> 瀏覽器編碼(UTF-8)--> 服務器解碼(ISO-8859-1) --> URLDecoder解碼(UTF-8)

3.jsp對於get方式的參數編碼:url="...."?sport=<%=URLEncoder.encoder("籃球","UTF-8") %>

服務器端獲取參數後解碼: Java代碼

Stringlinename = newString(request.getParameter("name").getBytes("ISO-8859-1"),"UTF-8");

說明:此時並沒有對server.xml的<Connector>配置useBodyEncodingForURI和URIEncoding屬性

編碼過程:瀏覽器編碼(UTF-8)--> 服務器解碼(ISO-8859-1) --> String.getBytes方法編碼(ISO-8859-1)--> 創建String解碼(UTF-8)

 

對範例2的說明:

可能大家都覺得對中文進行兩次UTF-8編碼後,進行一次ISO-8859-1解碼和一次UTF-8解碼,爲什麼得到的不是亂碼呢?

個人認爲java提供的URLEncoder和URLdecoder內部是做了某些處理的,和通String.getBytes獲取字節數組,再newString(bytes[], charset)編解碼方式使不一樣的。如java代碼:

String str = "漢字test";
            String str1 = URLEncoder.encode(str, "UTF-8");
            String str2 = URLEncoder.encode(str, "ISO-8859-1");
            String str3 = URLEncoder.encode(str, "UTF-8");
            String str4 = URLEncoder.encode(str3, "ISO-8859-1");
            //使用UTF-8編碼  解碼成功
            String str6 = URLDecoder.decode(str1, "UTF-8");
            //使用ISO-8859-1編碼  解碼失敗
            String str7 = URLDecoder.decode(str2, "ISO-8859-1");
            //編碼次數爲兩次,解碼一次,解碼失敗
            String str8 = URLDecoder.decode(str4, "UTF-8");
            //編碼次數等於解碼次數,且最終解碼方式爲字符串初始編碼方式就能解碼成功,
            //即使中間編碼方式爲ISO-8859-1
            String str9 = URLDecoder.decode(str8, "UTF-8");

從執行結果分析,個人覺得URLEncoder和URLDecoder對ASCII內的字符進行編碼, 無論URLEncoder.encode的charset參數是什麼,

得到的編碼結果都是一樣的,無論URLDecoder.decode的charset參數是什麼,得到的解碼結果都一樣,只要中文的起始編碼charset和最後解碼的chaset一致(這裏都是UTF-8),中間編碼和解碼次數對等(這裏均爲兩次), 則得到的結果就不會亂碼。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章