jsp教程:深入分析 JSP/Serverlet中的編碼問題

時(shí)間:2012-12-02 10:25來源:我愛IT技術(shù)網(wǎng) 作者:52ij 點(diǎn)擊: 158 次
(1) jsp頁面中的pageEncoding: 指定jsp編寫時(shí)所用的編碼(源文件編碼) 如果你用的是win98或winme的記事本來編寫的jsp, 則一定是常用的big5或gb2312; 如果用的是win2000或winXP的記事本時(shí), 保存時(shí)就可以選擇不同的編碼,包括ANSI(BIG5/GB2312)、UTF-8或Unic

 (1)  jsp頁面中的pageEncoding:   指定jsp編寫時(shí)所用的編碼(源文件編碼)

JSP/Serverlet中的編碼問題

        如果你用的是win98或winme的記事本來編寫的jsp, 則一定是常用的big5或gb2312;  如果用的是win2000或winXP的記事本時(shí), 保存時(shí)就可以選擇不同的編碼,包括ANSI(BIG5/GB2312)、UTF-8或Unicode(utf-16)
(2) jsp頁面中的contentType:   它指定的是jsp頁面最終在客戶端瀏覽器呈現(xiàn)時(shí)所見到的內(nèi)容的編碼。就是mozilla的charactrer encoding或是IE6的encoding等。

Jsp從源文件到最終用戶看到的html文件,會(huì)大致經(jīng)歷如下階段:
①  所編寫的源文件的保存, 由于計(jì)算機(jī)只能保存二進(jìn)制形式的內(nèi)容,而我們所寫的都是字符串形式的內(nèi)容,所以這里進(jìn)行的第一個(gè)階段即是由字符串到字節(jié)的編碼過程,這個(gè)階段所采用的就是PageEnco
ding所指定的編碼, 如這時(shí)指定的是GBK, 則會(huì)將一個(gè)漢字拆分成二個(gè)字節(jié)來保存,如果用的是utf-8則會(huì)用三個(gè)字節(jié)來保存。[jsp頁面的pageEncoding的默認(rèn)值是iso8859-1]
② 本階段是從.jsp文件中讀取二進(jìn)制信息并翻譯成.java文件的過程(這一過程由服務(wù)器如tomcat在運(yùn)行
時(shí)時(shí)完成), 服務(wù)器讀取出二進(jìn)制信息(字節(jié)), 然后用其保存時(shí)所使用的字符編碼來重新進(jìn)行解碼,將其還原成原始字串.   這時(shí)系統(tǒng)再使用UTF-8對字符串重新進(jìn)行編碼,并將其得到的字節(jié)信息寫入到x.java文件中(這與src中的.java文件不同,src中的.java文件采用的是平臺使用的字符集,而這里統(tǒng)一都用UTF-8)。
③  這一階段是完成從.java文件到源文件.class文件的編譯過程,這時(shí)系統(tǒng)會(huì)從.java文件中讀出字節(jié)數(shù)
據(jù),然后直接將其寫入.class文件中,所用編碼方式仍為UTF-8。
④  本階段是由tomcat從class文件中讀取二進(jìn)制信息,然后通過網(wǎng)絡(luò)發(fā)送出去, 具體用來實(shí)施這個(gè)工作的對象是response對象。而這個(gè)對象在發(fā)送數(shù)據(jù)前先要將數(shù)據(jù)根據(jù)UTF-8還原成原始字串,然后再按
contentType 所指定的編碼(如果沒設(shè)則與pageEncoding一樣)將字串編碼為字節(jié)流,然后再通過網(wǎng)
絡(luò)發(fā)送出去。
⑤  這階段的主要工作將由瀏覽器來完成.  此階段瀏覽器接收到字節(jié)流后,要負(fù)責(zé)將其解碼為字符串,而解碼所使用的字符碼式仍為contentType所指定的編碼方式。
 
      至此用戶就可以看到我們原先寫的字符串了。 其實(shí)上面幾步中前面幾步都沒可以省略不看,我們關(guān)
鍵要看的是最后兩步(即網(wǎng)絡(luò)發(fā)送前的編碼和到達(dá)瀏覽器后的解碼過程)來看下面幾種情況:
(1) <%@ page pageEncoding="GBK" contentType="text/html; charset=iso8859-1"%>
     假設(shè)頁面中有:  <h1>中</h1>
            當(dāng)走到第4步時(shí),服務(wù)器會(huì)讀取出字節(jié)并正確還原成字符串”<h1>中</h1>”, 這時(shí)response在發(fā)送前需要先將其變?yōu)樽止?jié)序列,所使用的編碼標(biāo)準(zhǔn)就是iso8859-1(由charset指定), 它會(huì)將一個(gè)英文解析為一個(gè)字節(jié),將一個(gè)中文也解析為一個(gè)字節(jié),這樣數(shù)據(jù)在發(fā)送前就已經(jīng)丟失了,所以到達(dá)瀏覽器時(shí)也必然為少了一個(gè)字節(jié)了。故我們會(huì)看到?輸出.
(2) <%@ page pageEncoding="GBK" contentType="text/html; charset=utf-8"%>
     假設(shè)頁面中有:  <h1>中</h1>
     發(fā)送前會(huì)將所有中文字符編碼為三個(gè)字節(jié)、英文字母和數(shù)字仍為1個(gè)字節(jié),然后送出,到瀏覽器后,再用同樣的字符編碼將字節(jié)解碼為字符串(中文三個(gè)一組),所以數(shù)據(jù)不會(huì)丟失,不會(huì)出現(xiàn)亂碼。編碼本身提供了一套標(biāo)準(zhǔn)來識別某個(gè)字節(jié)是否是中文字符的開始部分.
(3) <%@ page pageEncoding="utf-8" contentType="text/html; charset= GBK"%>
     假設(shè)頁面中有:  <h1>中</h1>
     發(fā)送前會(huì)將所有中文字符編碼為二個(gè)字節(jié)、英文字母和數(shù)字仍為1個(gè)字節(jié),然后送出,到瀏覽器后,再用同樣的字符編碼將字節(jié)解碼為字符串(中文二個(gè)一組),所以數(shù)據(jù)不會(huì)丟失,不會(huì)出現(xiàn)亂碼。
 
Jsp向servlet提交數(shù)據(jù)時(shí)的編碼問題:
      前面部分都一致,關(guān)鍵問題是字節(jié)流到達(dá)服務(wù)器后的解碼(字節(jié)->字符)過程, 與頁面不同的是它不采用contentType指定的字符編碼方式來解碼字節(jié),而是采用服務(wù)器(tomcat默認(rèn)值為iso8859-1)來解析,這樣一個(gè)字節(jié)就被還原成了一個(gè)字符, 這時(shí)如果我們的jsp指定的contentType是UTF-8, 就會(huì)出現(xiàn)本來是一個(gè)字符的三個(gè)字節(jié)被分別解析成了三個(gè)字符,所以亂碼也就產(chǎn)生了。
      我們可以通過手工的方式來設(shè)置字節(jié)的解碼方式,具體做法是在用request的getParameter方法前調(diào)用request的 setCharacterEncoding(“解碼方式”); 將編碼和解碼的碼式設(shè)為一致,如前面contentType設(shè)置為utf-8, 此處也就設(shè)置為utf-8, 這樣信息就能順利還原了。
      注:在tomcat中對于get方式提交的數(shù)據(jù)不論request的setCharacterEncoding設(shè)置的是何種字符編碼方式,服務(wù)器均采用ISO8859-1方式對其進(jìn)行解碼,所以我們要想得到正確數(shù)據(jù),就可以通過:
           String str =  request.getParameter(“xxx”);
           str =  new  String (str.getBytes(“ISO8859-1”,”contentType指定的編碼”);
這樣先將數(shù)據(jù)還原,然后再用發(fā)送時(shí)的字符集來進(jìn)行解碼,這樣就可將數(shù)據(jù)還原了.

(責(zé)任編輯:admin)