一文讓你今後告別HTTP亂碼(二)Response篇

概述

  開發Web項目的過程當中,常常遇到瀏覽器中顯示的內容亂碼,或者服務器獲取瀏覽器請求參數時亂碼的問題,不少同窗基本都是在遇到亂碼的時候去網上一頓搜索,而後看哪篇文章比較靠譜就照着上面的內容去配後亂碼成功消失了,而後就沒而後了...html

最後基本只是停留在知道怎麼樣設置能避免常見的亂碼問題,而不知道具體的原理,一旦遇到了網上查不到的亂碼場景就不知道如何解決了~web

  本文會深刻的讓你瞭解針對於HTTP請求時,這一去一回(Request,Response)之間,到底作了怎樣的事情,讓你完全告別Web項目中的亂碼煩惱。本文的內容是基於Tomcat 8.0.23版本的,其餘容器也能夠參考本文的內容,畢竟理論都是通的~數組

Response亂碼

  當你在瀏覽器中看到響應的內容是亂碼的時候,第一反應就是,是否是我程序的問題,是否是我程序吐出的內容就是個亂碼,因此才致使了瀏覽器裏面看到了亂碼。那麼接下來我將帶你過一遍Response的過程,以及對剛纔的猜想進行驗證~瀏覽器

  首先,我建了一個很是簡單的Web項目,裏面只有一個Servlet,做用是直接返回我要響應的內容~服務器

項目結構以下:工具

 

Servlet內容以下:編碼

web.xml內容以下:spa

接下來咱們在瀏覽器中訪問:http://localhost:8080命令行

 首先在Firefox中訪問,結果以下:xml

接下來再在QQ Browser中訪問,結果以下:

此時咱們看見2個瀏覽器中展現的內容不管是瀏覽器正文仍是下面的Response標籤中顯示的字符都是亂碼,而且是相同的亂碼內容~

那麼這個亂碼是怎麼產生的呢?回頭再去看咱們servlet中的代碼:

代碼中能夠看見咱們沒有指定任何的編碼相關內容,那麼Tomcat在將result字符串轉換成字節數組時會使用HTTP規範的默認編碼ISO-8859-1,因而輸出的內容就是將result進行ISO-8859-1編碼後的字節數組,

由於ISO-8859-1能表示的字符數量有限,它沒法表示中文,因此在此時Response的內容與就已是亂碼了。

而後Response到達瀏覽器,瀏覽器會獲取Response中的內容,由於Response中的響應頭中沒有指定信息的編碼類型,因此瀏覽器會嘗試根據編碼規則進行推測,並根據推測進行解碼,因爲我使用的是中文系統,Firefox

的正文部分採用的是GBK編碼,而Response中的內容則使用了UTF-8編碼。QQ Browser正文部分使用的也是GBK編碼,而Resopnse中的內容則使用了ISO-8859-1編碼(不一樣瀏覽器,或者同一個瀏覽器的不一樣版本解碼使用的編碼均可能會不同),

解碼以後就是我所看見的 ???~????! 亂碼了。

下面這段程序就能夠驗證上面的內容:

  上面的驗證本質上是由於在Servlet中處理Response的時候沒有指定編碼,從而致使了使用了默認的ISO-8859-1對Response的內容(楚楚街~賣得漂亮!)進行了編碼,可是由於ISO-8859-1沒法表示中文,結果在Servlet編碼

時就已經產生了亂碼,以後不管你怎麼解碼它都是個亂碼。

  接下來咱們改進下Servlet,使其在Response的時候使用UTF-8(由於UTF-8能夠表示中文)進行編碼,代碼以下:

而後咱們再次請求http://localhost:8080

Firefox結果以下:

QQ Browser結果以下:

從結果咱們能夠看出,Firefox中正文依然亂碼,而Response的內容正確解析了,而QQ Browser中正文和Response中的內容都是亂碼。

根據以前的分析,咱們已經知道Firefox的正文是GBK編碼,Response內容是UTF-8編碼,而QQ Browser中的正文也是GBK編碼,Response的內容是ISO-8859-1編碼。

下面代碼對上面的內容進行了驗證:

咱們在對Servlet返回給2個瀏覽器的Response進行一下抓包,看下Response的內容究竟是啥~

對Firefox的抓包:

對QQ Browser的抓包:

從結果咱們能夠看到2個瀏覽器收到的Response的結果都是相同的,其中Data部分都是e6a59ae6a59ae8a1977ee4b9b0e79a84e6bc82e4baae21,這串值就是

對 楚楚街~買的漂亮! 進行UTF-8編碼後的值。

到此爲止,作一個小總結:

  1.Response在返回前會對要返回的內容作編碼,在不指定(setCharacterEncoding("UTF-8"))的狀況下會使用默認的ISO-8859-1編碼。

  2.不一樣的瀏覽器在收到返回的Response時,獲取到的內容是一致的,以後瀏覽器會根據自身的策略對內容進行解析。

  繼續上面的亂碼問題,爲何此次使用UTF-8對中文進行了編碼後,瀏覽器裏面依然是亂碼呢?緣由就是在Response中沒有對響應的內容使用的是哪一種編碼作說明,致使了

瀏覽器不知道使用哪一種編碼作解碼,而後就使用了瀏覽器默認的解碼行爲進行解碼,從而致使了亂碼。

  接下來咱們爲Response加上響應頭Content-Type:text/plain; charset=utf-8來告訴瀏覽器,Response內容應該用什麼編碼來解碼,代碼以下:

上面的代碼中,咱們指定了2次編碼而且2次的編碼不一致,那麼到底會使用哪一個編碼呢?還會出現亂碼麼?看實際結果說話~

 Firefox結果:

QQ Browser結果:

咱們能夠看到,2個瀏覽器不管是正文部分仍是Response的內容中都正確的解碼了~

總結:

  1.Response須要告知瀏覽器使用哪種編碼來解碼其內容。

  2.Response所使用的編碼爲最後一次設置的編碼,也就是說後面的編碼設置信息會覆蓋掉前面的編碼設置信息。

接下來咱們再來使用命令行來請求下試試,以下圖:

發現結果竟然是亂碼,難道以前的結論是錯誤的?什麼鬼...

  其實以前的結論並沒錯,而是以前的結論須要加個限定條件(只適用於瀏覽器),咱們把HTTP請求的Response能夠劃分爲2個步驟,第一步是獲取到這個Response,第二步就是對

這個Response進行解析,上面的問題就出如今了第二步(解析)。由於瀏覽器是遵循HTTP規範的,HTTP規範中說明了響應頭中的Content-Type屬性中的charset指定的編碼就是Response

中內容的實際編碼,因此瀏覽器會使用這個charset中指定的編碼對Response中的內容進行解碼,那麼天然沒問題了,而命令行則不須要遵循HTTP中的規範,因此命令行並無關心charset指定

的內容,而是使用命令行默認的編碼進行解碼的,因此致使了亂碼,知道了問題的根本緣由,那麼是否是咱們改變了命令行的編碼就能夠正確顯示了呢?看下面結果:

首先咱們修改了命令行的編碼爲UTF-8(chcp 65001),而後從新請求後,發現顯示正常了~

到此爲止~Response時的亂碼問題成功解決啦~

Response亂碼總結:

  1.Response在返回前會對要返回的內容作編碼,在不指定編碼的狀況下會使用默認的ISO-8859-1編碼。

  2.不一樣的瀏覽器在收到返回的Response時,獲取到的內容是一致的,以後瀏覽器會根據自身的策略對內容進行解析。

  3.Response須要告知瀏覽器使用哪種編碼來解碼其內容。

  4.Response所使用的編碼爲最後一次設置的編碼,也就是說後面的編碼設置信息會覆蓋掉前面的編碼設置信息。

  5.瀏覽器會遵循HTTP規範,使用Content-Type屬性中的charset指定的編碼去解碼,而命令行工具則不會關注charset的內容,而是根據命令行自身的編碼方案進行解碼。

 

至此,一文讓你今後告別HTTP亂碼系列文章所有結束了~但願對遇到亂碼的同窗有所幫助,哪怕只有一點點~

附上上一篇文章的鏈接:一文讓你今後告別HTTP亂碼(一)Request篇

相關文章
相關標籤/搜索