Java Web中涉及的編解碼


用戶從瀏覽器發起一個HTTP請求,存在編碼的地方是URL、Cookie、Paramiter。服務器端接收到HTTP請求后要解析HTTP協議,其中URL、Cookie和POST表單參數要解碼,服務器端可能還需要讀取硬盤數據(數據庫、文件),這些數據都可能存在編碼問題。當Servlet處理完所有請求的數據后,需要將這些數據再編碼通過Socket發送到用戶請求的瀏覽器里,再經過瀏覽器解碼成為文本。這些過程用圖表示如下:

image

1.URL的編解碼

image

為了驗證瀏覽器是怎么編碼URL的,我們選擇FireFox瀏覽器並通過HTTPFox插件觀察請求的URL的實際內容:

image

從結果上看,PathInfo是UTF-8編碼,而QueryString是GBK編碼。至於為什么有%,是由URL的編碼規范FRC3986規定:瀏覽器編碼URL將非ASCII字符按照某種編碼格式編碼成16進制數字后將每個16進制表示的字節前加上“%”。

從上面的測試結果可知,瀏覽器對PathInfo和QueryString的編碼是不一樣的,不同的瀏覽器對PathInfo的編碼也可能不一樣。如Chrome會對請求“http://localhost:8080/中國?中國”轉變為“http://localhost:8080/%E4%B8%AD%E5%9B%BD?%E4%B8%AD%E5%9B%BD”,這里PathInfo和QueryString的編碼是一樣的,都是UTF-8編碼。

2.HTTP Header的編解碼

當客戶端發起一個HTTP請求時,除了上面的URL外還可能會在Header中傳遞其他的參數,如Cookie、redirectPath等,這些用戶設置的值很可能也會存在編碼問題。

在Tomcat中,對Header中的項進行解碼是在調用request.getHeader時進行的,如果請求的Header項沒有解碼則調用MessageBytes的toString方法,這個方法將從byte從char的轉化使用的默認編碼是ISO-8859-1,而我們也不能設置Header的其他解碼格式,所以如果你設置的Header中非ASCII字符解碼肯定會有亂碼。

我們在添加Header時也是同樣的道理,不要在Header中傳遞非ASCII字符,如果一定要傳遞可以先將字符用org.apache.catalina.util.URLEncoder編碼,然后再添加到Header中,這樣在瀏覽器到服務器的傳遞中就不會丟失信息了,我們在訪問這些項時再按照相應的字符集解碼就好了。

3.POST表單的編解碼

POST表單參數傳遞方式與QueryString不同,它是通過HTTP的BODY傳遞到服務端的。當我們在頁面上點擊提交按鈕時瀏覽器首先將根據頁面的ContentType的Charset編碼格式對表單填的參數進行編碼,然后提交到服務器端。在服務器端同樣也是用ContentType中的字符集進行解碼。所以通過POST表單提交的參數一般不會出現問題,而且這個字符集編碼是我們自己設置的。

另外,針對multipart/form-data類型的參數,也就是上傳的文件編碼,同樣也使用ContentType定義的字符集編碼。值得注意的地方是,上傳文件是用字節流的方式傳輸到服務器的本地臨時目錄,這個過程並沒有涉及字符編碼,而真正編碼是在將文件內容添加到parameters中時,如果用這個不能編碼將會用默認編碼ISO-8859-1來編碼。

4.HTTP BODY的編解碼

當用戶請求的資源服務端已經成功獲取后,這些內容將通過Response返回給客戶端瀏覽器,這個過程先要經過編碼再到瀏覽器進行解碼,瀏覽器根據HTML的<meta HTTP-equiv=“Content-Type” content=”text/html; charset=GBK”>中的charset來解碼。如果沒有定義,那么瀏覽器將會使用默認的編碼來解碼。

訪問數據庫都是通過客戶端JDBC驅動來完成的,用JDBC來存取數據要和數據的內置編碼保持一致,可以通過設置JDBC URL來指定。

5.JS中的編解碼

html文件本身中的js的編碼和當前頁面中的Content-Type保持一致。

對於采用<script src=”script.js”/>類型引入的js文件,瀏覽器就會以當前這個頁面的默認字符集解析這個JS文件,如果外部的JS文件的編碼格式與當前頁面的編碼格式一致,那么可以不設置這個charset。但是如果script.js文件的編碼格式與當前頁面的不一致,就必須要指定對應的字符集,要不然對於非ASCII字符就會出現亂碼。

6.其他需要編碼的地方

除了URL和參數編碼問題外,在服務端還有很多地方可能存在編碼,如可能需要讀取XML、Velocity模板引擎、JSP或者從數據庫讀取數據等。

image

 

參考資料:《深入分析Java Web技術》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM