?????? Tomcat
下最容易到的問(wèn)題就是中文亂碼問(wèn)題了
,
下面就來(lái)談?wù)勎以?/span>
Windows +Tomcat5
下調(diào)試
JSP
程序時(shí)
,
所碰到的問(wèn)題以及解決辦法。
??????
這次調(diào)試所遇到的亂碼問(wèn)題主要有三類:
一、
頁(yè)面字符亂碼。
即整個(gè)頁(yè)面出現(xiàn)漢字亂碼(不管是用
HTML
格式寫(xiě)的,還是用
print()
方法輸出的漢字,全部顯示為亂碼)。
二、
Request
傳遞亂碼。
在用
post
,
get
等方法,傳遞變量時(shí)出現(xiàn)亂碼;需要進(jìn)行
cookies
或者
session
調(diào)用時(shí)出現(xiàn)亂碼。
三、
數(shù)據(jù)庫(kù)存取亂碼。
在進(jìn)行數(shù)據(jù)庫(kù)存取時(shí),或者存入數(shù)據(jù)庫(kù),或者讀出數(shù)據(jù)時(shí)出再亂碼。
?
??????
下面就這三類亂碼進(jìn)行分析并談?wù)勎业慕鉀Q方法:
一、
頁(yè)面字符亂碼。
?
?????????????
我們先寫(xiě)下這樣的一個(gè)
jsp
文件:
????????????? //testPagErr.jsp
????????????? <%
???????????????????? out.println(“
能顯示中文嗎?
”);
%>
如果我們直接按照默認(rèn)的配置啟動(dòng)
Tomcat5
,然后訪問(wèn)這一個(gè)頁(yè)面的時(shí),將輸出的中文將顯示為亂碼。其原因很簡(jiǎn)單,這是由于在
Tomcat5
默認(rèn)的設(shè)置下,將按照
ISO-8859-1
進(jìn)行編碼。解決這個(gè)問(wèn)題最直接的做法是,有每個(gè)有中文輸出的
jsp
文件的開(kāi)頭加一句:
<%@ ?page contentType="text/html;charset=GBK" //
(改成
GB2312
亦可,本文中均以
GBK
為例)
%>
??????
但是這樣做存在很多問(wèn)題,首先,這一句開(kāi)指令在
include
的時(shí)候,不能夠被子文件繼承,因此,我們必須在子文件中重新加入這一句話,但如果大小寫(xiě)不話,就會(huì)出現(xiàn)類似于以下的錯(cuò)誤:
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).
??????
那么
,
這樣子定義就有點(diǎn)恐怖了,假如有一個(gè)要作
Head.jsp
的頭文件,我們?cè)囍谄渲屑尤?/span>
<%@ page contentType="text/html;charset=GBK" %>
,
要在眾多的文件中被包含,而這些文件是由不同的程序只寫(xiě)的,有的習(xí)慣用“
gbk
”
,
有的用“
GBK
”,還有喜歡用“
GB2312”,那怎么辦啊?難到要一個(gè)文件一個(gè)文件地去改過(guò)來(lái)?就算你可以用一些編輯器的
Replace in Files
功能把所有的文件更正過(guò)來(lái),但這樣做必然會(huì)影響系統(tǒng)的可移植性。
同樣
,
如果
"text/html;charset=GBK"
的間隔不一致的話,也會(huì)出錯(cuò),而且,一旦程被修改成這樣的模式,你的程序就不能在舊的
jsp/servlet container
上執(zhí)行了,因?yàn)榕f的規(guī)格是不允許在
include
文檔中再次中現(xiàn)
<%@ page ... %>
這樣的定義的。
因此上,如果采用上述方法的話,在一兩個(gè)頁(yè)面上也可行,但此法僅為權(quán)
益之計(jì)。
在
J2EE1.4
中,關(guān)于
jsp
的部分里有一個(gè)
<jsp-config>
的
XML Tag
,這個(gè)區(qū)塊是用來(lái)定義
jsp
的相關(guān)特殊屬性的,它包含所采用的
taglib
和下面我們要用到的
<jsp-property-group>
,定義字符編碼的方法就定義在
<jsp-property-group>
之中,找到你正在開(kāi)發(fā)的
webapps
目錄(一般在
$TOMCAT_HOME\webapps\your_web_site\
)下的
WEB-INF
,打開(kāi)
web.xml(
如果沒(méi)的話,就創(chuàng)建一個(gè)
)
,作如下修改:
?
<?xml version="1.0" encoding="ISO-8859-1"?>
?
<!—
這一段是
xml
head
的定義,特別注意,最后的
version="2.4"
,
Tomcat
5會(huì)去檢測(cè)這個(gè)版本的信息,只有
2.4
的才會(huì)去處理
jsp-config
中的參數(shù)
-->
<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">
<!— ------------------------------------------------------------------------------------------ -->
?
<!—
這一部分就是我們新加入的,起作用的區(qū)塊
-->
<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>
另外,如果
Tomcat5
與
Apache
整和,最好把
httpd.conf
中的
AddDefaultCharset
的值設(shè)為
GBK.
二、
R
equest
傳遞亂碼
。
按照
Tomcat
的默認(rèn)設(shè)置,在通過(guò)
表單
提交的數(shù)據(jù)將出現(xiàn)亂碼,其原因是中文字符的高位被丟失,
如:
成龍的
unicode
是
6210 9f99
,但是從
request
里面讀出來(lái)的是:
10 99
。
其原因是
form
表單和
request
方法中設(shè)置的編碼格式不一致,在上面,我們已經(jīng)將頁(yè)面編碼改成了
GBK
,因此上,我們只須將
request
的編碼改為
GBK
即可。
比較簡(jiǎn)單的解決方法是,在要用到
request
方法的地方加上這條語(yǔ)句:
request.setCharacterEncoding("GBK");
但這也將遇到與第一種方法同樣,當(dāng)幾個(gè)人同時(shí)寫(xiě)程序時(shí),或者,引用別人已寫(xiě)的程序的時(shí)候,也會(huì)存在移植不便的問(wèn)題。
更好的方法是,注冊(cè)
SetCharacterEncodingFilter
類:
在
$TOMCAT_HOME\webapps\your_web_site\WEB-INF\classes
目錄下新建一個(gè)名為
filters
的文件夾,然后把
$TOMCAT_HOME\webapps\jsp-examples\WEB-INF\classes\filters
的
SetCharacterEncodingFilter.class
文件拷到新建的
filters
下面,最后在
web.xml
中加入如下的兩個(gè)區(qū)塊:
<!-- 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
,也可以自己
編寫(xiě)
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);
??? }
?
}
用任意一個(gè)
java
編譯器編譯即可,編譯的時(shí)候注意包含
servlet-api.jar
包,它位于
$TOMCAT_HOME\common\lib\
下面。
??????
然后刪除
work
中的內(nèi)容,然后啟動(dòng)
Tomcat
,即可顯示中文了。
三、
數(shù)據(jù)庫(kù)存取亂碼
當(dāng)然,在寫(xiě)數(shù)據(jù)庫(kù)時(shí),也要保正數(shù)據(jù)庫(kù)的編碼與其它一致:
我們可以在
系統(tǒng)盤(pán)
windows
目錄下的
my.ini
文件,在文件中插入一行
default-character-set=GBK,
但上面說(shuō)了這么多,大家也應(yīng)該明白些了吧,改動(dòng)太多的默認(rèn)設(shè)置不是我的風(fēng)格,因此上,這一行還是不要加的好。
但不管怎么樣,我們還是要?jiǎng)?chuàng)建一個(gè)基于中文編碼的數(shù)據(jù)庫(kù),當(dāng)然,用客戶端登錄的時(shí)候,某些客戶用自動(dòng)把字體編碼轉(zhuǎn)換成中文編碼。在這里,我想說(shuō)一下在
DOS
下創(chuàng)建中文編碼數(shù)據(jù)庫(kù)的方法:
在進(jìn)入數(shù)據(jù)庫(kù)的時(shí)候,
用
mysql?--default-character-set=gbk?-u?root?-p?
這句話進(jìn)入
mysql
,
然后創(chuàng)建數(shù)據(jù)庫(kù),如:
create?database?admin;
這樣創(chuàng)建起來(lái)的數(shù)據(jù)庫(kù)就是基于中文編碼的了。
用連接數(shù)據(jù)庫(kù)的時(shí)候,讀出的數(shù)據(jù)也可能是亂碼,解決這個(gè)問(wèn)題的方法非常簡(jiǎn)單,只要在你建立數(shù)據(jù)庫(kù)連接的時(shí)候把
URL
設(shè)置成下面這個(gè)樣子就可以了:
URL=?jdbc:mysql://localhost:3306/my_database?useUnicode=true&characterEncoding=GBK
好了,說(shuō)了這么多,總結(jié)一句話結(jié)束吧,把各種地方的編碼統(tǒng)一起來(lái),那么,所在的亂碼問(wèn)題就都解決了!
?
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=513467