編碼&解碼
通過下圖我們可以了解在javaweb中有哪些地方有轉碼:

使用者想伺服器發送一個http請求,需要編碼的地方有url、cookie、parameter,經過編碼後伺服器接受http請求,解析http請求,然後對url、cookie、parameter進行解碼。在伺服器進行業務邏輯處理過程中可能需要讀取資料庫、本地檔案或者網絡中的其他檔案等等,這些過程都需要進行編碼解碼。當處理完成後,伺服器将資料進行編碼後發送給用戶端,浏覽器經過解碼後顯示給使用者。在這個整個過程中涉及的編碼解碼的地方較多,其中最容易出現亂碼的位置就在于伺服器與用戶端進行互動的過程。
上面整個過程可以概括成這樣,頁面編碼資料傳遞給伺服器,伺服器對獲得的資料進行解碼操作,經過一番業務邏輯處理後将最終結果編碼處理後傳遞給用戶端,用戶端解碼展示給使用者。是以下面我就請求對javaweb的編碼&解碼進行闡述。
請求
用戶端想伺服器發送請求無非就通過四中情況:
1、url方式直接通路。
2、頁面連結。
3、表單get送出
4、表單post送出
url方式
對于url,如果該url中全部都是英文的那倒是沒有什麼問題,如果有中文就要涉及到編碼了。如何編碼?根據什麼規則來編碼?又如何來解碼呢?下面lz将一一解答!首先看url的組成部分:
在這url中浏覽器将會對path和parameter進行編碼操作。為了更好地解釋編碼過程,使用如下url
将以上位址輸入到浏覽器url輸入框中,通過檢視http 封包頭資訊我們可以看到浏覽器是如何進行編碼的。下面是ie、firefox、chrome三個浏覽器的編碼情況:
可以看到各大浏覽器對“我是”的編碼情況如下:
查閱上篇部落格的編碼可知對于path部分firefox、chrome、ie都是采用utf-8編碼格式,對于query string部分firefox、chrome采用utf-8,ie采用gbk。至于為什麼會加上%,這是因為url的編碼規範規定浏覽器将ascii字元非 ascii 字元按照某種編碼格式編碼成 16 進制數字然後将每個 16 進制表示的位元組前加上“%”。
當然對于不同的浏覽器,相同浏覽器不同版本,不同的作業系統等環境都會導緻編碼結果不同,上表某一種情況,對于url編碼規則下任何結論都是過早的。由于各大浏覽器、各個作業系統對url的uri、querystring編碼都可能存在不同,這樣對伺服器的解碼勢必會造成很大的困擾,下面我們将已tomcat,看tomcat是如何對url進行解碼操作的。
解析請求的 url 是在 org.apache.coyote.http11.internalinputbuffer 的 parserequestline 方法中,這個方法把傳過來的 url 的 byte[] 設定到 org.apache.coyote.request 的相應的屬性中。這裡的 url 仍然是 byte 格式,轉成 char 是在 org.apache.catalina.connector.coyoteadapter 的 converturi 方法中完成的:
從上面的代碼可知,對uri的解碼操作是首先擷取connector的解碼集,該配置在server.xml中
如果沒有定義則會采用預設編碼iso-8859-1來解析。
對于query string部分,我們知道無論我們是通過get方式還是post方式送出,所有的參數都是儲存在parameters,然後我們通過request.getparameter,解碼工作就是在第一次調用getparameter方法時進行的。在getparameter方法内部它調用org.apache.catalina.connector.request 的 parseparameters 方法,這個方法将會對傳遞的參數進行解碼。下面代碼隻是parseparameters方法的一部分:
從上面代碼可以看出對query string的解碼格式要麼采用設定的chartset要麼采用預設的解碼格式iso-8859-1。注意這個設定的chartset是在 http header中定義的contenttype,同時如果我們需要改指定屬性生效,還需要進行如下配置:
上面部分詳細介紹了url方式請求的編碼解碼過程。其實對于我們而言,我們更多的方式是通過表單的形式來送出。
表單get
我們知道通過url方式送出資料是很容易産生亂碼問題的,是以我們更加傾向于通過表單形式。當使用者點選submit送出表單時,浏覽器會更加設定的編碼來編碼資料傳遞給伺服器。通過get方式送出的資料都是拼接在url後面(可以當做query string??)來送出的,是以tomcat伺服器在進行解碼過程中uriencoding就起到作用了。tomcat伺服器會根據設定的uriencoding來進行解碼,如果沒有設定則會使用預設的iso-8859-1來解碼。假如我們在頁面将編碼設定為utf-8,而uriencoding設定的不是或者沒有設定,那麼伺服器進行解碼時就會産生亂碼。這個時候我們一般可以通過new string(request.getparameter(“name”).getbytes(“iso-8859-1″),”utf-8”) 的形式來擷取正确資料。
表單post
對于post方式,它采用的編碼也是由頁面來決定的即contenttype。當我通過點選頁面的submit按鈕來送出表單時,浏覽器首先會根據ontenttype的charset編碼格式來對post表單的參數進行編碼然後送出給伺服器,在伺服器端同樣也是用contenttype中設定的字元集來進行解碼(這裡與get方式就不同了),這就是通過post表單送出的參數一般而言都不會出現亂碼問題。當然這個字元集編碼我們是可以自己設定的:request.setcharacterencoding(charset) 。
<a href="http://cmsblogs.com/?p=1510">原文連結</a>