使用 tomcat 時(shí),相信大家都回遇到中文亂碼的問(wèn)題,具體表現(xiàn)為通過(guò)表單取得的中文數(shù)據(jù)為亂碼。

一、初級(jí)解決方法

通過(guò)一番檢索后,許多人采用了如下辦法,首先對(duì)取得字符串按照 iso8859-1 進(jìn)行解碼轉(zhuǎn)換,然后再按照 gb2312 進(jìn)行編碼,最后得到正確的內(nèi)容。示例代碼如下:

String  para = new String( request.getParameter("para").getBytes("iso8859-1"), "gb2312");

具體的原因是因?yàn)槊绹?guó)人在寫(xiě) tomcat 時(shí)默認(rèn)使用 iso8859-1 進(jìn)行編碼造成的。

 然而,在我們的 servlet 和 jsp 頁(yè)面中有大量的參數(shù)需要進(jìn)行傳遞,這樣轉(zhuǎn)換的話會(huì)帶來(lái)大量的轉(zhuǎn)換代碼,非常不便。

二、入門(mén)級(jí)解決方法

后來(lái),大家開(kāi)始寫(xiě)一個(gè)過(guò)濾器,在取得客戶(hù)端傳過(guò)來(lái)的參數(shù)之前,通過(guò)過(guò)濾器首先將取得的參數(shù)編碼設(shè)定為 gb2312 ,然后就可以直接使用 getParameter 取得正確的參數(shù)了。這個(gè)過(guò)濾器在 tomcat 的示例代碼
jsp-examples 中有詳細(xì)的使用示例,   其中過(guò)濾器在 web.xml 中的設(shè)定如下,示例中使用的是日文的編碼,我們只要修改為 gb2312 即可

    <filter>
        <filter-name>Set Character Encoding</filter-name>
        <filter-class>filters.SetCharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>EUC_JP</param-value>
        </init-param>
    </filter>

過(guò)濾器的代碼如下:
public class SetCharacterEncodingFilter implements Filter {

    // 編碼的字符串
    protected String encoding = null;

   // 過(guò)濾器的配置
    protected FilterConfig filterConfig = null;

   // 是否忽略客戶(hù)端的編碼
    protected boolean ignore = true;

   // 銷(xiāo)毀過(guò)濾器
    public void destroy() {

        this.encoding = null;
        this.filterConfig = null;

    }

   // 過(guò)濾方法
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)
          throws IOException, ServletException {

        // 如果使用過(guò)濾器,忽略客戶(hù)端的編碼,那么使用通過(guò)過(guò)濾器設(shè)定編碼
        if (ignore || (request.getCharacterEncoding() == null)) {
            String encoding = selectEncoding(request);
            if (encoding != null)
                request.setCharacterEncoding(encoding);
        }

        // 傳送給下一個(gè)過(guò)濾器
        chain.doFilter(request, response);

    }


    // 初始化過(guò)濾器
    public void init(FilterConfig filterConfig) throws ServletException {

        this.filterConfig = filterConfig;
        this.encoding = filterConfig.getInitParameter("encoding");
        String value = filterConfig.getInitParameter("ignore");
        if (value == null)
            this.ignore = true;
        else if (value.equalsIgnoreCase("true"))
            this.ignore = true;
        else if (value.equalsIgnoreCase("yes"))
            this.ignore = true;
        else
            this.ignore = false;

    }

    // 返回過(guò)濾器設(shè)定的編碼
    protected String selectEncoding(ServletRequest request) {

        return (this.encoding);

    }
}

然而在 tomcat5 中,即使使用過(guò)濾器,仍然可能取得亂碼,原因何在呢?

三、高級(jí)解決方法

這是因?yàn)椋?FONT face="Courier New">在 tomcat4 和 tomcat5 中對(duì)參數(shù)的處理是不一樣的,在 tomcat4 中 get 與 post 的編碼是一樣的,所以只要在過(guò)濾器中通過(guò) request.setCharacterEncoding 設(shè)定一次就可以解決 get 與 post 的問(wèn)題。然而,在 tomcat5 中,get 與 post 的處理是分開(kāi)進(jìn)行的

在 tomcat 5 中,為了解決編碼問(wèn)題,tomcat 的作者作了很多努力,具體表現(xiàn)為在 tomcat 的配置文件 server.xml 中對(duì) Connector 元素增加了如下的配置參數(shù),專(zhuān)門(mén)用來(lái)對(duì)編碼進(jìn)行直接的配置

URIEncoding   用來(lái)設(shè)定通過(guò) URI 傳遞的內(nèi)容使用的編碼,tomcat 將使用這里指定的編碼對(duì)客戶(hù)端傳送的內(nèi)容進(jìn)行編碼。

什么是 URI 呢?
java doc 的說(shuō)明中如下說(shuō)明:URI 是統(tǒng)一資源標(biāo)識(shí)符,而 URL 是統(tǒng)一資源定位符。因此,籠統(tǒng)地說(shuō),每個(gè) URL 都是 URI,但不一定每個(gè) URI 都是 URL。這是因?yàn)?URI 還包括一個(gè)子類(lèi),即統(tǒng)一資源名稱(chēng) (URN),它命名資源但不指定如何定位資源。

也就是說(shuō),我們通過(guò) get 方法提交的參數(shù)實(shí)際上都是通過(guò) uri 提交的,都由這個(gè)參數(shù)管理,如果沒(méi)有設(shè)定這個(gè)參數(shù),則 tomcat 將使用默認(rèn)的 iso8859-1 對(duì)客戶(hù)端的內(nèi)容進(jìn)行編碼。

useBodyEncodingForURI 使用與 Body 一樣的編碼來(lái)處理 URI, 這個(gè)設(shè)定是為了與 tomcat4保持兼容,原來(lái)在 tomcat4 和 tomcat5 中隊(duì)參數(shù)的處理是不一樣的,在 tomcat4 中 get 與 post 的編碼是一樣的,所以只要在過(guò)濾器中通過(guò) request.setCharacterEncoding 設(shè)定一次就可以解決 get 與 post 的問(wèn)題。然而,在 tomcat5 中,get 與 post 的處理是分開(kāi)進(jìn)行的,對(duì) get 的處理通過(guò) 前面的 URIEncoding 進(jìn)行處理,對(duì) post 的內(nèi)容依然通過(guò) request.setCharacterEncoding 處理,為了保持兼容,就有了這個(gè)設(shè)定。

將 useBodyEncodingForURI 設(shè)定為真后,就可以通過(guò) request.setCharacterEncoding 直接解決 get 和 post 中的亂碼問(wèn)題

這樣,我們可以通過(guò)在 server.xml 中設(shè)定 URIEncoding 來(lái)解決 get 方法中的參數(shù)問(wèn)題,使用過(guò)濾器來(lái)解決 post 方法中的問(wèn)題。

或者也可以通過(guò)在 server.xml 中設(shè)定 useBodyEncodingForURI 為 true ,配合過(guò)濾器來(lái)解決編碼的問(wèn)題。

在這里,我強(qiáng)烈建議在網(wǎng)站的創(chuàng)作過(guò)程中,全程使用 utf-8 編碼來(lái)徹底解決亂碼問(wèn)題。

具體操作如下:
1、頁(yè)面內(nèi)容使用 utf-8 格式保存,在頁(yè)面中加入 <mete http-equiv="contentType" content="text/html;charst=utf-8">

2、服務(wù)器端的 server.xml 中設(shè)定 useBodyEncodingForURI = true

3、使用過(guò)濾器,過(guò)濾器設(shè)定編碼為 utf-8