楊麗慧
(河北民族師范學(xué)院 信息中心,河北 承德 067000)
如何解決Tomcat的亂碼
楊麗慧
(河北民族師范學(xué)院 信息中心,河北 承德 067000)
針對(duì)在JSP/Servlet程序設(shè)計(jì)中,服務(wù)器用Tomcat在頁(yè)面上經(jīng)常會(huì)看到亂碼。就這個(gè)問(wèn)題提出幾種解決的方法。
tomcat;JSP/Servlet;GET;POST;Filter
開(kāi)發(fā)項(xiàng)目時(shí),用JSP/Servlet編程,服務(wù)器用tomcat,經(jīng)常會(huì)看到亂碼。所以就亂碼的問(wèn)題同大家探討一下。
在JSP/Servlet中主要在以下幾個(gè)地方可以設(shè)置編碼,<%@page pageEncoding=“UTF-8”%>,建議在每個(gè)頁(yè)面上都加上pageEncoding設(shè)定,讓?xiě)?yīng)用服務(wù)器能正確把JSP文件按照設(shè)定的編碼轉(zhuǎn)換為Java文件,只要這個(gè)pageEncoding設(shè)置正確就可以避免靜態(tài)內(nèi)容的亂碼。有的時(shí)候沒(méi)有設(shè)置也沒(méi)有亂碼,那是因?yàn)閼?yīng)用服務(wù)器還可以讀取<%@page content-Type=“text/html;charset=UTF-8”%>中的charset作為備選方案,雖然這是JSP規(guī)范中要求的,但是難保有的容器沒(méi)有實(shí)現(xiàn)或?qū)崿F(xiàn)有BUG,所以有時(shí)候在某個(gè)應(yīng)用服務(wù)器下 (如Tomcat)不設(shè)置pageEncoding也可以,但是同樣的頁(yè)面拿到別的應(yīng)用服務(wù)器下就有可能出現(xiàn)亂碼。
新下載的Tomcat沒(méi)有經(jīng)過(guò)任何特殊的設(shè)置,無(wú)論是GET和POST都出現(xiàn)亂碼。首先設(shè)置HTTP Connector(server.xml中監(jiān)聽(tīng)8080端口的那個(gè)Connector),加上URIEncoding=“UTF-8”,消除了GET亂碼,再在 JSP頁(yè)面中第一句加入<%request. setCharacterEncoding(“UTF-8”)%>,消除了POST亂碼。通過(guò)上面兩個(gè)設(shè)置我們發(fā)現(xiàn),URIEncoding控制的是GET字符集編碼,Request的CharacterEncoding控制的是POST字符集編碼。
上面提到的<%@page contentType=“text/html;charset=UTF-8”%>,除了聲明返回給客戶(hù)端的流是text/html外,同時(shí)設(shè)置了Response的CharacterEncoding,相當(dāng)于執(zhí)行了Response.setCharacterEncoding (“UTF-8”)這段代碼。它保證了服務(wù)器端生成的動(dòng)態(tài)內(nèi)容到達(dá)客戶(hù)端也不會(huì)亂碼。
但有一種情況下也不會(huì)出現(xiàn)亂碼,就是如下例這種情況,前提是沒(méi)有設(shè)置Request的CharacterEncoding:
1 protected void doPost(HttpServletRequest request ,HttpServletResponse response) throws ServletException,IOException{
2 response.getWriter().write(request.getParameter(“xxxxx”));
3}
這種情況下提交過(guò)來(lái)的表單數(shù)據(jù)其實(shí)是ISO-8859-1的編碼,而返回給客戶(hù)端又沒(méi)有<%@page contentType=“text/html;charset=UTF-8”%>的設(shè)置,所以還是ISO-8859-1的編碼,但是為什么沒(méi)有亂碼呢?其實(shí)已經(jīng)亂碼了,如果在第2行下斷點(diǎn)的話(huà),會(huì)發(fā)現(xiàn)request.getParameter(“xxxxx”)的返回值就是亂碼??梢杂靡痪銳ava代碼來(lái)解釋為什么客戶(hù)端顯示結(jié)果沒(méi)有亂碼,如下:
System.out.println(new String(“你好,世界”.get-Bytes(“ISO-8859-1”),“ISO-8859-1”);
很奇怪這句代碼,明明是中文,應(yīng)該用GB2312或GBK之類(lèi)的字符集編碼來(lái)getBytes,卻用了ISO-8859-1,事實(shí)證明,這種互逆操作對(duì)字符串本身沒(méi)有任何影響,只要getBytes和new String的時(shí)候字符集編碼是一致的就不會(huì)引起亂碼。
上面這句代碼正好說(shuō)明了數(shù)據(jù)從客戶(hù)端POST到服務(wù)器端時(shí)是ISO-8859-1編碼,然后從服務(wù)器端寫(xiě)回到客戶(hù)端還是ISO-8859-1編碼,所以就沒(méi)有造成亂碼,如果這里不是直接寫(xiě)回到客戶(hù)端,而是forward到另一個(gè)JSP頁(yè)面,而這個(gè)頁(yè)面恰好使用了<%@page contentType=“text/html;charset=UTF-8”%>來(lái)設(shè)置Response的CharacterEncoding,那么在頁(yè)面中輸出xxxxx還會(huì)產(chǎn)生亂碼,同樣用一句Java代碼來(lái)解釋?zhuān)缦拢?/p>
System.out.println(new String(“你好,世界”.get-Bytes(“ISO-8859-1”),“UTF-8”));
所以,最后結(jié)論是如果想POST到服務(wù)器端不亂碼就要設(shè)置Request的CharacterEncoding,寫(xiě)回到客戶(hù)端不亂碼就要設(shè)置 Response的CharacterEncoding,若是JSP頁(yè)面要設(shè)置<%@page contentType=“text/html;charset=UTF-8”%>。
GET請(qǐng)求時(shí),需要對(duì) queryString使用 encodeURIComponent()編碼之后再提交到服務(wù)器。這是XMLHttpRequest規(guī)范所要求的。
POST請(qǐng)求時(shí),不需要使用encodeURIComponent()。
通過(guò)對(duì)應(yīng)用程序下斷點(diǎn)發(fā)現(xiàn),GET請(qǐng)求和POST請(qǐng)求的數(shù)據(jù)發(fā)送到服務(wù)器端都是正常的沒(méi)有亂碼,但是服務(wù)器端生成的動(dòng)態(tài)內(nèi)容寫(xiě)回客戶(hù)端卻是亂碼,說(shuō)明Response的CharacterEncoding設(shè)置錯(cuò)誤,反過(guò)來(lái)我們?cè)傧胍幌拢揪蜎](méi)有設(shè)置過(guò)Response的CharacterEncoding,為什么呢?因?yàn)槭且訟JAX的方式提交表單,返回后不像JSP頁(yè)面那樣有<%@page contentType=“text/html;charset=UTF-8”%>來(lái)設(shè)置Response的CharacterEncoding,所以就會(huì)出錯(cuò)。
綜合上述,解決的辦法就是各大網(wǎng)站提出的通用解決方案Filter,如果應(yīng)用沒(méi)有用到AJAX,只設(shè)置Request的CharacterEncoding即可,否則Response的CharacterEncoding也要設(shè)置。
TP3
A
2095-3763(2012)02-0062-02
2012-01-05
楊麗慧(1972-),女,河北張家口人,河北民族師范學(xué)院信息中心副教授,碩士。