java web 開發 編碼問題詳解

java web 開發 編碼問題詳解
瀏覽器 IE/FireFox -------——---->Servlet容器--------——---------------->顯示頁面

編碼        使用容器的URIEncoding解碼/request解碼,再編碼發出響應             解碼

一、請求
我把用戶發送請求方式不同引起的中文問題劃分了四種類型:

1、表單的get提交

2、表單的post提交

3、頁面鏈接傳遞中文參數(參考get提交)

4、地址欄中參數直接輸入中文提交(不討論,違背尋常規則,而且這種方式很難控制)

1.get提交
對於這種,影響的有tomcat的URIEncoding。
瀏覽器會根據自己的頁面的編碼格式作爲起始編碼格式(右擊菜單編碼有顯示的),把字符使用瀏覽器的編碼格式編碼成byte字節進行傳輸。到了tomcat這裏,tomcat會使用URIEncoding進行重新編碼(解碼),如果tomcat沒有配置的話就會使用iso-8859-1對byte進行重新編碼(解碼)成字符。如果瀏覽器得編碼格式爲UTF-8,且tomcat沒有配置重新編碼(解碼)格式的話,就可以使用下面的方式拿到正確的字符了new String(request.getParameter("text").getBytes("iso-8859-1"),"utf-8") 上的意思就是說,把剛纔的字符,用iso-8859-1進行編碼成byte,還原回去,再使用uft-8對byte進行重新編碼(解碼)成字符。(這個方法就是剛纔從瀏覽器到tomcat過來的逆向過程)

2.post提交
對於這種情況,response.setCharacterEncoding有影響,當沒有對response.setCharacterEncoding設置的時候值爲null,則默認採用iso-8859-1來進行重新編碼(解碼)。
瀏覽器根據自己頁面的編碼格式作爲起始編碼格式,把字符進行編碼成byte進行傳輸,到了tomcat,tomcat不進行干涉其中的重新編碼(解碼)格式。如果response.getCharacterEncoding爲null,那麼默認採用iso-8859-1進行重新編碼(解碼)成字符,如果設置了,就按照設置的編碼格式進行重新編碼(解碼)字符。

jsp:pageEncoding="GB18030"  jsp頁面的編碼格式,即jsp會被解析成servlet時,採用的編碼格式。如果不配置,默認採用iso-8859-1,當jsp文件保存編碼類型和pageEncoding不一致時就會出現jsp內部解析亂碼。Eclipse現在默認pageEncoding就是文件的編碼格式,修改pageEncoding就會修改文件的編碼格式。該參數還有一個功能,就是在JSP中不指定contentType參數,也不使用response.setCharacterEncoding方法時指定對服務器響應進行重新編碼(解碼)的編碼,從而pageEncoding會影響瀏覽器的編碼格式。

jsp:contentType="text/html;charset=UTF-8"  的作用是指定對服務器響應進行重新編碼(解碼)的編碼。設定瀏覽器的編碼格式。也就是說瀏覽器提交數據就會使用這個編碼格式。相當於response.setCharacterEncoding來改變編碼,但是改變的只是jsp請求的response編碼格式。不能改變裏面所有其他的ajax請求的編碼格式。在沒有設定的情況下默認採用ISO-8859-1格式。

meta中
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
當前面pageEncoding和contentType都沒有設置的情況下,被解析成的html頁面就會採用這種編碼方式。來把byte解析成瀏覽器顯示的信息。

jsp頁面中 pageEncoding--->contentType--->meta 默認缺省。pageEncoding寫了後面的都可以不用寫,默認繼承。

jsp頁面中的設定編碼優先級response.setCharacterEncoding--->contentType--->pageEncoding  層層覆蓋。

request.setCharacterEncoding("UTF-8")的作用是設置對客戶端請求進行重新編碼(解碼)的編碼。
該方法用來指定對瀏覽器發送來的數據進行重新編碼(或者稱爲解碼)時,使用的編碼。對post方法有效。

使用response.setCharacterEncoding方法時,用該參數指定對服務器響應進行重新編碼(解碼)的編碼。

tomcat:默認URIEncoding爲iso-8859-1,可以設置。設置之後,會影響get方法和頁面鏈接傳遞中文的參數字符編碼。

關於UTF-8和GBK轉化之間的問題
當UTF-8轉化成GBK,再從GBK轉化成UTF-8的時候,偶數漢字可以在UTF-8,GBK兩者中互相轉換,而奇數個漢字則不能。

關於BIG5
關於其他的轉碼問題,如果使用的是簡體中文的字符,即使編碼和解碼都是使用BIG5,部分字符仍然無法解析,是亂碼。

關於ISO-8859-1
ISO-8859-1是不支持中文的,所以就算中文字符使用ISO-8859-1進行編碼,最後再用ISO-8859-1進行重新編碼(解碼)的話,拿到的字符也不能顯示中文。即換言之,ISO-8859-1不能作爲把字符變成byte的編碼格式使用。

ajax
xmlHttp.responseText的請求的默認編碼是UTF-8 。當然可以重新設置,通過在Request Headers中設置Content-Type:application/x-www-form-urlencoded; charset=utf-8。爲什麼ajax和之前的不同呢?因爲ajax不是使用默認的瀏覽器跳轉提交方式,而是使用httprequest提交方式,默認跳轉方式會讀取瀏覽器的編碼格式,而httprequest不會,所以ajax就會設置自己的默認的編碼格式進行提交,即UTF-8.而使用ajax的post方法提交,無需再設定request的重新編碼(解碼)格式,因爲request不再是默認的null,已經修改爲UTF-8,所以不用轉換直接拿出即可。而對於get方法的話,需要參考tomcat的URIEncoding重新編碼(解碼)。


二、返回信息
而response如果沒有顯式設置的話,不管request的編碼是什麼,response的編碼就是ISO-8859-1。

對於response返回的信息如:response.getWriter().println就可以看到這個編碼設置的作用了。而對於使用request.setAttribute等傳遞數據的話,這個編碼格式設置了也沒用。

當使用response.getWriter().println打印到瀏覽器時,在沒有設置response的時候默認爲null,而在服務器端則默認使用iso-8859-1進行編碼成byte,等到了瀏覽器,發現response的信息header中沒有相關編碼設置,就會去取window系統的編碼格式,中文系統默認爲GBK/GB2312。所以,打印出來的頁面的瀏覽器編碼格式爲GB2312。而如果設置了response的編碼格式,那麼就算到了瀏覽器,瀏覽器解析也會按照設置的編碼格式重新編碼(解碼)。

當使用response.getWriter().println打印到本地文件時,即使設置了response,在發出時,採用的是設置的編碼格式編碼成byte,等到了客戶端,客戶端會用系統的編碼格式重新編碼(解碼)文件,對於windows默認就是GB2312/GBK,所以最好再response發出時就設置編碼的格式爲GBK。

至於爲什麼打印到瀏覽器,頭文件的信息就寫入編碼格式,而打印到本地文件,頭文件中就沒有寫入編碼格式的問題,還沒有得到證實。猜測:後端傳送到瀏覽器時,瀏覽器使用包含重新編碼(解碼)格式的。而傳送文件時,沒有使用重新編碼(解碼)格式的,使用的是操作系統的編碼格式存儲文件。

如果設置了response.setCharacterEncoding。那麼就會按照這個編碼格式傳送到前端,瀏覽器並用這種方式重新編碼(解碼)。也就是說在傳送的頁面的文本信息head中的content-type已經設置成了response.setCharacterEncoding定義的編碼格式,來用作重新編碼(解碼)。

ajax
ajax使用的是response.responseText來進行獲取信息,也就是說,也是需要使用到response的編碼格式的。ajax不會再對該編碼格式進行任何修改。只是接受而已。


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