Tomcat5+Mysql中文亂碼問題的解決方法

noter發表於2007-05-24

Tomcat 下最容易到的問題就是中文亂碼問題了,下面就來談談我在Windows +Tomcat5下除錯JSP程式時,所碰到的問題以及解決辦法。

       這次除錯所遇到的亂碼問題主要有三類:

一、頁面字元亂碼。

即整個頁面出現漢字亂碼(不管是用HTML格式寫的,還是用print()方法輸出的漢字,全部顯示為亂碼)。

二、Request 傳遞亂碼。

在用postget等方法,傳遞變數時出現亂碼;需要進行cookies或者session呼叫時出現亂碼。

三、資料庫存取亂碼。

在進行資料庫存取時,或者存入資料庫,或者讀出資料時出再亂碼。

 

       下面就這三類亂碼進行分析並談談我的解決方法:

一、頁面字元亂碼。

 

              我們先寫下這樣的一個jsp檔案:

              //testPagErr.jsp

              <%

                     out.println(“能顯示中文嗎?”);

%>

如果我們直接按照預設的配置啟動Tomcat5,然後訪問這一個頁面的時,將輸出的中文將顯示為亂碼。其原因很簡單,這是由於在Tomcat5 預設的設定下,將按照ISO-8859-1進行編碼。解決這個問題最直接的做法是,有每個有中文輸出的jsp檔案的開頭加一句:

<%@  page contentType="text/html;charset=GBK" //(改成GB2312亦可,本文中均以GBK為例)%>

       但是這樣做存在很多問題,首先,這一句開指令在include的時候,不能夠被子檔案繼承,因此,我們必須在子檔案中重新加入這一句話,但如果大小寫不話,就會出現類似於以下的錯誤:

org.apache.jasper.JasperException: /top.jsp(1,1) Page directive: illegal to have multiple occurrences of contentType with different values (old: text/html;charset=gbk, new: text/html;charset=GBK).

       那麼,這樣子定義就有點恐怖了,假如有一個要作Head.jsp的標頭檔案,我們試著在其中加入<%@ page contentType="text/html;charset=GBK" %>要在眾多的檔案中被包含,而這些檔案是由不同的程式只寫的,有的習慣用“gbk,有的用“GBK”,還有喜歡用“GB2312,那怎麼辦啊?難到要一個檔案一個檔案地去改過來?就算你可以用一些編輯器Replace in Files功能把所有的檔案更正過來,但這樣做必然會影響系統的可移植性。

同樣,如果"text/html;charset=GBK"的間隔不一致的話,也會出錯,而且,一旦程被修改成這樣的模式,你的程式就不能在舊的jsp/servlet container上執行了,因為舊的規格是不允許在include文件中再次中現<%@ page ... %>這樣的定義的。

因此上,如果採用上述方法的話,在一兩個頁面上也可行,但此法僅為權益之計。

J2EE1.4中,關於jsp的部分裡有一個<jsp-config> XML Tag,這個區塊是用來定義jsp的相關特殊屬性的,它包含所採用的taglib和下面我們要用到的<jsp-property-group>,定義字元編碼的方法就定義在<jsp-property-group>之中,找到你正在開發的webapps目錄(一般在$TOMCAT_HOME/webapps/your_web_site/)下的WEB-INF,開啟web.xml(如果沒的話,就建立一個),作如下修改:

 

<?xml version="1.0" encoding="ISO-8859-1"?>

 

<!— 這一段是xml head的定義,特別注意,最後的version="2.4"Tomcat5會去檢測這個版本的資訊,只有2.4的才會去處理jsp-config中的引數 -->

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-app_2_4.xsd"

version="2.4">

<!— ------------------------------------------------------------------------------------------ -->

 

<!— 這一部分就是我們新加入的,起作用的區塊 -->

<jsp-config>

       <jsp-property-group>

           <description>

              Special property group for JSP Configuration JSP example.

           </description>

           <display-name>JSPConfiguration</display-name>

           <url-pattern>*.jsp</url-pattern>

           <el-ignored>true</el-ignored>

           <page-encoding>GBK</page-encoding>

           <scripting-invalid>flase</scripting-invalid>

           <include-prelude></include-prelude>

           <include-coda></include-coda>

 

           <description>

              Special property group for JSP Configuration JSP example.

           </description>

           <display-name>JSPConfiguration</display-name>

           <url-pattern>*.html</url-pattern>

           <el-ignored>true</el-ignored>

           <page-encoding>GBK</page-encoding>

           <scripting-invalid>flase</scripting-invalid>

           <include-prelude></include-prelude>

           <include-coda></include-coda>

       </jsp-property-group>

</jsp-config>

<!— ------------------------------------------------------------------------------------------ -->

</web-app>

另外,如果Tomcat5Apache整和,最好把httpd.conf中的AddDefaultCharset的值設為GBK.

二、equest傳遞亂碼

按照Tomcat的預設設定,在通過表單提交的資料將出現亂碼,其原因是中文字元的高位被丟失,如:

成龍的unicode 6210 9f99 ,但是從request裡面讀出來的是: 10 99

其原因是form表單和request方法中設定的編碼格式不一致,在上面,我們已經將頁面編碼改成了GBK,因此上,我們只須將request的編碼改為GBK即可。

比較簡單的解決方法是,在要用到request方法的地方加上這條語句:request.setCharacterEncoding("GBK");

但這也將遇到與第一種方法同樣,當幾個人同時寫程式時,或者,引用別人已寫的程式的時候,也會存在移植不便的問題。

更好的方法是,註冊SetCharacterEncodingFilter類:

$TOMCAT_HOME/webapps/your_web_site/WEB-INF/classes目錄下新建一個名為filters的資料夾,然後把$TOMCAT_HOME/webapps/jsp-examples/WEB-INF/classes/filtersSetCharacterEncodingFilter.class檔案拷到新建的filters下面,最後在web.xml中加入如下的兩個區塊:

<!-- Example filter to set character encoding on each request -->

    <filter>

        <filter-name>Set Character Encoding</filter-name>

        <filter-class>filters.SetCharacterEncodingFilter</filter-class>

        <init-param>

            <param-name>encoding</param-name>

            <param-value>GBK</param-value>

        </init-param>

    </filter>

 

<!-- Example filter mapping to apply the "Set Character Encoding" filter

     to *all* requests processed by this web application -->

 

    <filter-mapping>

        <filter-name>Set Character Encoding</filter-name>

        <url-pattern>/*</url-pattern>

    </filter-mapping>

       如果找不到SetCharacterEncodingFilter.class,也可以自己編寫SetCharacterEncodingFilter.java檔案,程式碼如下:

*

  * filename: SetCharacterEncodingFilter.java

*

package filters;

 

import java.io.IOException;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.UnavailableException;

 

 

public class SetCharacterEncodingFilter implements Filter {

 

    protected String encoding = null;

    protected FilterConfig filterConfig = null;

    protected boolean ignore = true;

 

    public void destroy() {

        this.encoding = null;

        this.filterConfig = null;

    }

 

    public void doFilter(ServletRequest request, ServletResponse response,

                         FilterChain chain)

       throws IOException, ServletException {

        // Conditionally select and set the character encoding to be used

        if (ignore || (request.getCharacterEncoding() == null)) {

            String encoding = selectEncoding(request);

            if (encoding != null)

                request.setCharacterEncoding(encoding);

        }

 

       // Pass control on to the next filter

        chain.doFilter(request, response);

 

    }

 

    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;

 

    }

 

 

    // ------------------------------------------------------ Protected Methods

 

    protected String selectEncoding(ServletRequest request) {

        return (this.encoding);

    }

 

}

用任意一個java編譯器編譯即可,編譯的時候注意包含servlet-api.jar包,它位於$TOMCAT_HOME/common/lib/下面。

       然後刪除work中的內容,然後啟動Tomcat,即可顯示中文了。

三、資料庫存取亂碼

當然,在寫資料庫時,也要保正資料庫的編碼與其它一致:

我們可以在系統盤windows目錄下的my.ini檔案,在檔案中插入一行default-character-set=GBK,但上面說了這麼多,大家也應該明白些了吧,改動太多的預設設定不是我的風格,因此上,這一行還是不要加的好。

但不管怎麼樣,我們還是要建立一個基於中文編碼的資料庫,當然,用客戶端登入的時候,某些客戶用自動把字型編碼轉換成中文編碼。在這裡,我想說一下在DOS下建立中文編碼資料庫的方法:

在進入資料庫的時候,mysql --default-character-set=gbk -u root -p 這句話進入mysql然後建立資料庫,如:create database admin;這樣建立起來的資料庫就是基於中文編碼的了。

用連線資料庫的時候,讀出的資料也可能是亂碼,解決這個問題的方法非常簡單,只要在你建立資料庫連線的時候把URL設定成下面這個樣子就可以了:URL= jdbc:mysql://localhost:3306/my_database?useUnicode=true&characterEncoding=GBK

好了,說了這麼多,總結一句話結束吧,把各種地方的編碼統一起來,那麼,所在的亂碼問題就都解決了!

【來源】

 

相關文章