JSP編碼以及亂碼解決總結

一直以來對JSP中出現亂碼的問題都很混亂,現經過查閱資料,對JSP亂碼這個問題有比較深刻的認識,下邊是我的一些個人總結,希望給同樣迷惑的人帶來幫助。 同時如果不對,希望得到提醒,共同進步。

首先,說說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)查看得知瀏覽器的編碼(解碼)和<%@pagecontentType="text/html;charset=GBK" %>或 response.setCharacterEncoding("UTF-8")設置的編碼是一致的。 因此:只要響應結果不是亂碼,則瀏覽器顯示結果一定不會是亂碼(伺服器對響應編碼和瀏覽器對響應解碼的編碼是一樣的)。 出現亂碼的情況是:瀏覽器編碼 ---> 伺服器解碼得到的結果是亂碼 ---> 造成響應有亂碼 --> 瀏覽器顯示亂碼

3.<meta http-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方式提交的數據

表單中POST方式提交的情況:可以通過request.setCharacterEncoding(charset),來設置對瀏覽器提交的數據使用什麼樣的編碼進行解碼。如果不設置時,伺服器默認使用ISO-8859-1來解碼請求參數。如果頁面的contentType="GBK", 此時要想得到正確的結果,則:String name = new String(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)

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設置無效

<Connector port="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代碼 String linename = new String(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代碼String linename = 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代碼 String linename = new String(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獲取位元組數組,再new String(bytes[], charset)編解碼方式使不一樣的。如java代碼:String str = "my中國心";String str1 = URLEncoder.encode(str, "UTF-8"); //my%E4%B8%AD%E5%9B%BD%E5%BF%83String str4 = URLEncoder.encode(str1, "ISO-8859-1"); //my%25E4%25B8%25AD%25E5%259B%25BD%25E5%25BF%2583String str5 = URLEncoder.encode(str1, "UTF-8"); //%25E4%25B8%25AD%25E5%259B%25BD%25E5%25BF%2583String str6 = URLDecoder.decode(str4, "GBK"); //my%E4%B8%AD%E5%9B%BD%E5%BF%83String str7 = URLDecoder.decode(str4, "GBK"); //my%E4%B8%AD%E5%9B%BD%E5%BF%83String str8 = URLDecoder.decode(str5, "UTF-8"); //my中國心從執行結果分析,個人覺得URLEncoder和URLDecoder對ASCII內的字元進行編碼,無論URLEncoder.encode的charset參數是什麼,得到的編碼結果都是一樣的,無論URLDecoder.decode的charset參數是什麼,得到的解碼結果都一樣只要中文的起始編碼charset和最後解碼的chaset一致(這裡都是UTF-8),中間編碼和解碼次數對等(這裡均為兩次), 則得到的結果就不會亂碼


推薦閱讀:

【轉載】對目前一線降壓藥物特點的總結
本周總結《傾城之戀》
總結出幾點基本的銷售技巧
從盤口總結炒股十要和炒股十不要
13位裝修師傅總結的54條避坑指南,條條都是不可多得的實戰經驗!

TAG:亂碼 | 編碼 | 總結 |