Web實際應用中的編碼問題

一、 JSP頁面有關編碼的介紹

---->>如果不做任何設置,頁面默認ISO-8859-1編碼(Western European)。
---->><%@ page contentType="text/html; charset=UTF-8" %>

等同於response.setContentType("text/html; charset=UTF-8"); 這裏對ContentType進行說明下

這裏的ContentType是response的ContentType,意思就是告訴瀏覽器
我的數據是text/html,編碼是UTF-8,因此瀏覽器會以UTF-8的編碼進行展示。

---->> <%@ page pageEncoding="UTF-8" %>

1.等同於告訴Eclipse我這個頁面以什麼編碼方式存儲
當然你可以修改jsp頁面的編碼方式,使其和pageEncoding不一樣。
Eclipse的編碼有一個默認方式,叫determine from content type
也就是說內容是怎麼編的,我就怎麼來。你要修改它也拿你沒辦法不是.
2.同時告訴Tomcat以什麼方式讀取這個JSP頁面(這裏大家有疑問,我問候再解釋)

---->>在<%@ page %>中如果沒有contentType則根據pageEncoding產生contentType

假設pageEncoding="UTF-8"則默認爲response.setContentType("text/html;charset=utf-8")
假設pageEncoding="GBK"則默認爲response.setContentType("text/html;charset=gbj")

---->>在<%@ page %>中如果沒有pageEncoding則根據contentType的charset來編碼

同樣的如果沒有pageEncoding則默認pageEncoding爲contentType的charset.
這裏pageEncoding起的作用是告訴Tomcat這個JSP文件以什麼編碼讀取。

---->><meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type" />
---->><meta charset="UTF-8" > 

這兩個是HTML標籤。。如果response的header上沒有ContentType,
則瀏覽器會以這兩個的編碼進行展示.但是,看下面。。。。
在JSP中 如果<%@ page %> 沒有contentType和pageEncoding。
則默認response.setContentType("text/html")
這就意味着默認編碼是ISO-8859-1所以JSP中meta的charset和contentType無效。

---->>request.setCharacterEncoding("GBK");

此方法是設置從瀏覽器端傳過來數據的編碼方式。
注意該方法只對POST的數據有效。

---->>resp.setContentType("application/json;charset=ISO-8859-1");

此處的編碼對於瀏覽器的編碼無影響,即如果用的是中文,charset=UTF-8或者GBK
對瀏覽器都不會產生亂碼。只要不是在中文的情況下使用ISO就可以.

---->>resp.setCharacterEncoding("GBK");

這裏的作用是設置返回給瀏覽器內容的編碼方式,並可以設置頁面的編碼。
前提是該請求是進行頁面的跳轉,如果是ajax請求數據,數據的編碼方式則跟
ajax請求發出的頁面的編碼方式相同。

默認情況下頁面是以ISO編碼,如果數據中存在中文則默認改爲GB2312,如果
此時的編碼方式爲UTF-8,則會產生亂碼。

注意:在servlet中設置中文的編碼和該servlet對應java文件保存的編碼方式無關。

二、 數據從服務器到瀏覽器的傳輸

這裏我先做一個簡單的架構。A代表瀏覽器,B代表服務器(Tomcat)。
B上面運行着許多Servlet.每一個Servelt可能編碼不一樣。
(這裏Servlet的編碼指的是Servlet的java文件在系統上的編碼).
每個Servelt的編碼其實不影響他在服務瀏覽器時對編碼產生的影響。
這就好比兩個不同編碼的Servlet,當我們用文本打開時可以看到它們都擁有"中國"的字符
它們在硬盤上保存的二進制可能是不同的,當它們對"中國"以UTF-8進行編碼時產生的字節碼是一樣的

在Tomcat看來JSP也是一個Servlet,例如我們有一個index.jsp則對應一個index_jsp.java。
這裏我不對Tomcat的內部原理進行詳解,大家只要知道index_jsp.java是一個Servlet即可。

A請求B,B上的Servlet沒有亂碼,並且告訴A你應該以什麼方式展示(ContentType)則沒有亂碼
亂碼最容易出現的地方是當我們訪問jsp的時候。大多數時候在index_jsp.java中已經是亂碼了
還記得我說過<%@ page pageEncoding="UTF-8" %>的兩個作用,其中第二個作用是告訴Tomcat
以什麼方式讀取jsp文件,也就是說pageEncoding的編碼與實際index.jsp頁面的編碼一致時,
生成的index_jsp.java文件裏就沒有亂碼。有興趣大家去看Tomcat源碼。
注:
contentType和pageEncoding的互相替代作用上面說過,不做解釋了。
當contentType和pageEncoding都有時,contentType爲utf-8,pageEncoding爲gbk
並且index.jsp以gbk編碼,也不會出現亂碼.

三、 數據從瀏覽器到服務器的傳輸

數據從瀏覽器到服務器傳輸時,其編碼方式以當前瀏覽器頁面的編碼方式相同。
即頁面是UTF-8編碼就是UTF-8,是GBK就是GBK。
在Serlvet中可以通過設置request.setCharacterEncoding("GBK");對數據進行解碼。
但這種方式只對通過post方式上傳的數據有效。
get方式的編碼默認爲ISO-8859-1。
get方式有兩種情況:一種是在地址欄直接輸入,另一種是頁面url跳轉。下面分情況討論下
------>>頁面url跳轉方式: 這裏三種提供get方式亂碼問題的解決辦法:
1.在tomcat的server.xml中修改
2.Serlvet中獲取參數new String(request.getParameter("key").getBytes("ISO-8859-1"),"Encoding")
第二種方式在詳細說明一下,在get方式發送請求時,是按頁面的編碼方式對數據進行編碼。
當請求發送到tomcat之後,會默認以ISO-8859-1的編碼進行解碼。因此我們需要以ISO的編碼進行還原,
在是頁面的編碼進行編碼,所以這裏的Encoding設置的是頁面的編碼方式。
3.使用Tomcat8
首先不建議get方式傳中文,如果需要使用第二種解決方式。
------>>地址欄直接輸入:如果url帶有中文則默認先UTF-8編碼,再ISO-8859-1.
與頁面的url不同的是 頁面的get方式編碼取決於頁面編碼,地址欄瀏覽器默認utf-8.

四、 溫馨提示

如果大家看Tomcat源碼,想了解jsp是如何形成index_jsp.java文件的。
建議大家看幾個文件:Compile.java,Generator.java,PageInfo.java,ParserController.java

以上我說的編碼親測有效,如果有什麼出入的地方,歡迎交流。

原創摘自:http://beadlechen.github.io/content/blog.html#category=software#article=encode3

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