1. 程式人生 > >Javaweb中亂碼問題詳解

Javaweb中亂碼問題詳解

為什麼需要編碼?

由於人類的語言太多了,在計算機中表示這些語言的符號太多了,導致在計算機中無法通過一個基本的儲存單元--位元組來表示,

所以我們就需要進行一些拆分和翻譯工作,以使計算機可以理解我們的語言。

計算機中都有哪些編碼?

ASCII碼:共128個字元,用一個位元組的低7位表示,0-31是控制字元,32-126是列印字元;

ISO-88559-1:擴充套件了ASCII碼,共256個字元,包含了大多數西歐編碼,屬於單位元組編碼;

GB2312:雙位元組編碼,編碼範圍A1-F7,A1-A9是符號區,共682符號,B0-F7是漢字區,包含6763漢字;

GBK:擴充套件GB2312,編碼範圍8140-FEFE(不包含XX7F),共23940碼位,能夠表示21003個漢字,相容GB2312;

GB18030:可能是單位元組,雙位元組,四位元組編碼,應用不廣泛;

UTF-16:每個字元用兩個位元組表示,可以表示所有符號,它大大簡化了字串的操作,故Java以UTF-16作為記憶體的字元儲存格式;

UTF-8:採用一種變長技術,相比UTF-16,儲存空間變小了,而且可以減少網路傳輸的流量。


最理想的中文編碼方式是:UTF-8


HTTP請求中的編碼問題?

我們主要是按照http請求的流程來梳理一下在一個http請求和響應中間,都有哪些地方進行了編解碼,從而在我們平時的專案中

再遇到亂碼問題更容易排查到問題的原因。(使用tomcat)

https://localhost:8080/project/test/首頁?name=張三

我們看上面的這個URL,我們看到在URI中含有中文,在引數中,也含有中文。

=============get========================

1、首先,在我們請求的時候,瀏覽器會對我們的請求進行編碼,如果URL中存在非ASCII編碼,瀏覽器會對URI中的字元(首頁)使用瀏覽器的

預設編碼進行編碼,請求引數(張三)會用本機預設編碼進行編碼。並且根據編碼規範,會在被編碼的位元組前加%。

2、然後到了tomcat中,如果不修改,那麼URI中會預設使用ISO-8859-1解碼,引數中會先檢視header中的ContentType中定義的Charset,

如果沒有定義,就會在第一次呼叫requestParameter的時候使用預設的ISO-8859-1解碼。

不過我們可以通過配置檔案修改預設tomcat的預設編碼,<Connector URIEncoding="UTF-8"/> ,不過這裡需要注意的是,如果只是這樣設定了,

tomcat僅僅會使用該編碼對引數中的資訊進行解碼,對於URI中的資訊還是使用ISO-8859-1進行解碼,所以我們需要改成如下配置:

<Connector URIEncoding="UTF-8" useBodyEncodingForURI="true"/>,這樣就會對URI部分使用配置的編碼進行解碼。

以上都會對於get請求而言。


這裡我們先說下header,有時我們HTTP請求中,我們也會在header中攜帶一些資訊,這裡面的資訊如果存在非ASCII字元,那麼在接收端也需

要進行解碼,就像tomcat,在首次呼叫request.getHeader預設就是使用ISO-8859-1進行解碼,而且我們不能通過其他方式修改解碼格式,所以,

如果header中存在非ASCII字元的話,首先通過URIEncoder進行編碼,在新增到header中,不然很可能出現亂碼。

=============post==========================

對於post請求而言,它的引數的解碼也是在第一次呼叫request.getParameter是進行的,而且post方式和get方式傳遞引數的方式不同,post是

在HTTP的body中進行引數傳輸的。我們在頁面提交的時候,瀏覽器會先對引數使用ContentType中的編碼進行編碼,服務端也用ContentType中

的編碼進行解碼,而且,這個字符集編碼我們可以通過request.setCharacterEncoding(charset)進行設定。


編碼字符集可以通過response.setCharacterEncoding(charset)進行設定,它會覆蓋request.setCharacterEncoding(charset)設定的值。並且會

通過header的ContentType返回客戶端,瀏覽器會通過該編碼進行解碼。

瀏覽器解碼首先會通過Header中的ContentType中的charset進行解碼,如果不存在,會尋找頁面中的<meta>標籤中有沒有設定編碼,如果還沒有,

就會使用瀏覽器預設的編碼進行解碼。


對於post請求而言,如果不想每次都要通過request設定編碼,也可以使用過濾器進行修改編碼。但是都僅僅對post請求有效。



此文參考《深入分析JAVA WEB技術內幕》


如果有不對的地方,請留言指正。