解決Tomcat 5 下中文亂碼問題
使用 tomcat
時,相信大家都回遇到中文亂碼的問題,具體表現為通過表單取得的中文資料為亂碼。
下面是本人解決之路。
一、初級解決方法
通過一番檢索後,許多人採用瞭如下辦法,首先對取得字串按照
iso8859-1 進行解碼轉換,然後再按照 gb2312 進行編碼,最後得到正確的內容。示例程式碼如下:
String para = new
String( request.getParameter("para").getBytes("iso8859-1"),
"gb2312");
具體的原因是因為美國人在寫 tomcat 時預設使用 iso8859-1 進行編碼造成的。
然而,在我們的
servlet 和 jsp
頁面中有大量的引數需要進行傳遞,這樣轉換的話會帶來大量的轉換程式碼,非常不便。
二、入門級解決方法
後來,大家開始寫一個過濾器,在取得客戶端傳過來的引數之前,通過過濾器首先將取得的引數編碼設定為 gb2312 ,然後就可以直接使用 getParameter 取得正確的引數了。這個過濾器在 tomcat 的示例程式碼
jsp-examples 中有詳細的使用示例, 其中過濾器在 web.xml 中的設定如下,示例中使用的是日文的編碼,我們只要修改為 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
</init-param>
</filter>
過濾器的程式碼如下:
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 {
// 如果使用過濾器,忽略客戶端的編碼,那麼使用通過過濾器設定編碼
if (ignore ||
(request.getCharacterEncoding() == null)) {
String encoding =
selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}
// 傳送給下一個過濾器
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 String selectEncoding(ServletRequest
request) {
return (this.encoding);
}
}
然而在 tomcat5
中,即使使用過濾器,仍然可能取得亂碼,原因何在呢?
三、高階解決方法
這是因為,在 tomcat4 和 tomcat5 中對引數的處理是不一樣的,在 tomcat4 中 get 與 post
的編碼是一樣的,所以只要在過濾器中通過 request.setCharacterEncoding 設定一次就可以解決 get 與 post 的問題。然而,在
tomcat5 中,get 與 post 的處理是分開進行的
在 tomcat 5 中,為了解決編碼問題,tomcat
的作者作了很多努力,具體表現為在 tomcat 的配置檔案 server.xml 中對 Connector
元素增加了如下的配置引數,專門用來對編碼進行直接的配置
URIEncoding 用來設定通過 URI
傳遞的內容使用的編碼,tomcat 將使用這裡指定的編碼對客戶端傳送的內容進行編碼。
什麼是 URI 呢?
java doc
的說明中如下說明:URI 是統一資源識別符號,而 URL 是統一資源定位符。因此,籠統地說,每個 URL 都是 URI,但不一定每個
URI 都是 URL。這是因為 URI 還包括一個子類,即統一資源名稱
(URN),它命名資源但不指定如何定位資源。
也就是說,我們通過
get 方法提交的引數實際上都是通過 uri 提交的,都由這個引數管理,如果沒有設定這個引數,則 tomcat 將使用預設的 iso8859-1
對客戶端的內容進行編碼。
useBodyEncodingForURI 使用與 Body 一樣的編碼來處理 URI, 這個設定是為了與
tomcat4保持相容,原來在 tomcat4 和 tomcat5 中隊引數的處理是不一樣的,在 tomcat4 中 get 與 post
的編碼是一樣的,所以只要在過濾器中通過 request.setCharacterEncoding 設定一次就可以解決 get 與 post 的問題。然而,在
tomcat5 中,get 與 post 的處理是分開進行的,對 get 的處理通過 前面的 URIEncoding 進行處理,對 post 的內容依然通過
request.setCharacterEncoding 處理,為了保持相容,就有了這個設定。
將 useBodyEncodingForURI
設定為真後,就可以通過 request.setCharacterEncoding 直接解決 get 和 post
中的亂碼問題。
這樣,我們可以通過在 server.xml 中設定 URIEncoding 來解決 get
方法中的引數問題,使用過濾器來解決 post 方法中的問題。
或者也可以通過在 server.xml 中設定
useBodyEncodingForURI 為 true ,配合過濾器來解決編碼的問題。
在這裡,我強烈建議在網站的創作過程中,全程使用
utf-8 編碼來徹底解決亂碼問題。
具體操作如下:
1、頁面內容使用 utf-8
格式儲存,在頁面中加入 <mete http-equiv="contentType"
content="text/html;charst=utf-8">
2、伺服器端的 server.xml 中設定
useBodyEncodingForURI = true
3、使用過濾器,過濾器設定編碼為 utf-8