(一)JSP的中文亂碼問題
其根源在於:Web容器(Tomcat)默認的字元處理編碼是iso-8859-1,對於需要在瀏覽器頁面上顯示中文的JSP程序,
但在程序中並沒有指定中文的字符集,那麼中文將在瀏覽器頁面上顯示為亂碼.當然,前面所說的是指在Tomcat伺服器下的,其他服務
器有些不是這樣的,比如BEA Weblogic和IBM Websphere是從操作系統中取得默認的編碼,然後按該編碼來轉碼所有用戶請求.Struts中
文問題有三種:發送請求時的中文問題、處理響應結果的中文問題和國際化資源文件的中文問題.
1. 發送請求時的中文問題
客戶機向伺服器發送請求時,根據所使用瀏覽器的不同可能會有不同的編碼形式.不過通常情況下在請求到達Web容器前要將之轉碼,
轉成某種固定的編碼以方便Web應用的處理.這種問題有三種處理方法:
第一種(針對Tomcat 5 對POST請求有效,GET請求無效,因為Tomcat 5 對POST和GET請求時分別處理的)可以採用設置用戶請求對象的編碼形式,也就是以HttpServletRequest對象的編碼的形式來進行用戶請求的轉碼:
//將用戶請求轉碼為GB2312、GB18030、GBK、UTF-8 等型,具體轉為什麼類型的編碼以您的jsp文件的編碼方式為準,java、jsp 、js 、css應保持一致的編碼方式.這裡以GBK為例.
request.setCharacterEncoding("GBK");
第二種(對GET請求有效),可以在Servlet中對用戶輸入的數據進行轉碼.Web容器接受到一個請求時,它會將它發往某個處理的Servlet.在Servlet中直接獲取用戶請求的數據,然後將之轉碼為需要的格式,例如把數據轉換為GBK格式:
String username = request.getParameter("username");
username = new String(username.getBytes("iso-8859-1」), "GBK");
以上兩種方法都是很常用的,但第一種是每個頁面都要去修改,當JSP頁面很多時比較麻煩,第二種就每個發送的數據都要轉碼,也很麻煩.
第三種,就是採用Filter過濾器方式,將用戶的所有請求都通過過濾器進行轉碼,這種方法就克服了以上兩種方法的缺點.代碼如下:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain ) throws IOException, ServletException {
request.setCharacterEncoding("GBK");
//response.setContentType("text/html;charset=GBK");
chain.doFilter(request, response);
}
這裡轉碼為GBK過濾器的主要代碼,當然還要把這個類要在web.xml文件中部署.
2. 處理響應結果的中文問題
響應的結果包括Servlet、JSP和HTML三種情況,可以通過以下方式設置響應結果編碼:
對於Servlet,可以在Servlet中為其設置響應代碼類型,代碼如下:
response.setContentType("text/html;charset=GBK"); 也可把這句加到上面的Filter中,如註釋掉的部分.
有人說用 response.setCharacterEncoding("GBK"); 無效,必須用 response.setContentType("text/html;charset=GBK"); 本人沒試過.
對於JSP,是比較方便的,只需要在JSP最前部分按如下方式聲明:
<%@ page contentType="text/html;charset=GBK"%>
對於HTML,其和JSP文件基本類似,也是在頁面最前部分按如下方式聲明:
<head>
<META HTP-EQUIV="contentType" CONTENT="text/html;charset=GBK">
</head>
3. 國際化資源文件的中文問題
一個Struts應用程序中,可以配置多個資源包,無論是Action、ActionForm還是JSP都可以訪問這些包中的資源.資源包就是由擴展名為.properties的文件組成的一組具有相同前綴的文件,如ApplicationResources_zh_CN.properties、ApplicationResources_zh.properties和ApplicationResources.properties.這些文件就構成一個Struts的資源包,它們都有一個統一的前綴ApplicationResources,凡是有相同前綴的資源文件就都屬於一個包.
當用MyEclipse編寫資源文件時,默認是不能保存中文的,因為默認保存編碼的格式是ISO-8859-1,這就需要修改為gb2312或者gbk編碼格式.Windons -->Preferences-->General -->Content Types-->Text-->Java Properties File,在最下方把其Default encoding改為"UTF-8」,然後"update」就可以保存中文了.但就這樣保存的中文還是不能夠在頁面上使用的,因為Web容器默認是使用ISO-8859-1,也就會把中文用ISO-8859-1的格式發送給客戶頁面,顯示的還是亂碼,這就是JAVA國際化的問題.JAVA是支持unicode編碼格式的,unicode是國際統一通用編碼,不管什麼格式的編碼轉化為unicode編碼肯定不會顯示亂碼的.這個時候就是需要把資源文件的UTG-8編碼格式轉化為unicode編碼格式,而SUN公司又提供了這樣的一種工具.在JDK的安裝目錄bin下,有一個叫native2ascii可執行文件,這個是專門來進行資源文件轉碼的.打開cmd,進入JDK的bin目錄下,把資源文件拷貝到該目錄下,執行該命令.比如:
native2ascii –encoding GBK ApplicationResources.properties ApplicationResources_zh_CN.properties 就是把GBK編碼格式ApplicationResources.properties轉化為unicode編碼格式ApplicationResources_zh_CN.properties,這樣顯示頁面時就不會出現亂碼了.
(二)Websphere 默認的字元處理編碼要看 :
管理控制台--->伺服器--->應用程序伺服器--->server1--->java和進程管理--->進程定義--->java虛擬機--->通用jvm參數 的設置了,如為,-Dfile.encoding=GB2312 -Dclient.encoding.override=GBK 則是GBK.
我們可以通過如下判定:
用ieHTTPHEADERS 等工具查看POST請求中的請求參數,漢字是經過Encoding的(是按哪種字符集編碼要看jsp文件的編碼方式了),
由 % 間隔的十六進位數組成,如下 jsp文件的字符集是UTF-8,form 表單提交,用ieHTTPHEADERS 工具查得請求參數為:
struts.token.name=struts.token&struts.token=HPADE1CXRJ0PASL2V7RQFVXJLLFB1OUE&ptoId=244&
orgName=組織名稱&orgId=&oscId=&oscType=H1&ptoType=01&impDate=2009-06-16
&details=具體情況
orgName=組織名稱 經UTF-8 編碼的,其中文對應的是"組織名稱" ,E7BB84 是"組"的十六進位表示,
E7BB87 是"織"的十六進位表示等.
form表提交后,在ACTION中查看 "組織名稱" 變為亂碼: "緇勭粐鍚嶇О"
通過以下代碼分析:
String JinZhi16 = Integer.valueOf("E7",16).toString(); // 把E7 轉為十進位,這裡JinZhi16 = 231 ,BB 對應的十進位:187
System.out.println("JinZhi16 = " JinZhi16);
// 這裡的231、187,132等都是通過Integer.valueOf("E7",16).toString()分別把對應的E7、BB、84 等轉過來的十進位數字.
byte[] bt = new byte[]{(byte)231,(byte)187,(byte)132,(byte)231,(byte)187,(byte)135,(byte)229,(byte)144,(byte)141,(byte)231,(byte)167,(byte)176};
System.out.println("GB18030 = " new String(bt,"GB18030"));
System.out.println("GBK = " new String(bt,"GBK"));
System.out.println("UTF-8 = " new String(bt,"UTF-8"));
String aa = new String(bt,"GB18030");
System.out.println("GBK = " new String(aa.getBytes("GBK"),"UTF-8"));
String encoding=System.getProperty("file.encoding");
System.out.println("Default System Encoding: " encoding);
輸出內容:
JinZhi16 = 231
GB18030 = 緇勭粐鍚嶇О
GBK = 緇勭粐鍚嶇О
UTF-8 = 組織名稱
GBK = 組織名稱
Default System Encoding: UTF-8
我們發現:form表單提交 orgName=組織名稱(即"組織名稱") 到 ACTION ,是 "緇勭粐鍚嶇О"
這樣的亂碼,而 System.out.println("GB18030 = " new String(bt,"GB18030")); 輸出的也為"緇勭粐鍚嶇О" ,可假設其
編碼字符集也為GB18030或GBK,用通過System.out.println("GBK = " new String(aa.getBytes("GBK"),"UTF-8")); 得知確為GBK
或GB18030.GB18030是 GBK的超集,他支持3--4位元組的編碼,不過這兩個標準都支持GB2312-80 .
查看WebSphere的 "通用jvm參數" 的設置了是 -Dfile.encoding=GB2312 -Dclient.encoding.override=GBK
把-Dfile.encoding=GB2312 -Dclient.encoding.override=GBK 改為
-Dfile.encoding=UTF-8 -Dclient.encoding.override=UTF-8 就可以解決亂碼了(對get 和 post 有效).
修改完上述參數要從起WebSphere的服務,遠程登錄到安裝WebSphere的機器上,你的was發布的ip 就是WebSphere所在的機器, 其用戶名和密碼同登錄到發布was 的WebSphere的控制台一樣,因為本來就是同一台機器.登錄到WebSphere控制台 ,伺服器 ——>應用程序伺服器 找到對應的節點名稱如 "cncaitKaifaNode03" ,在控制面板 - > 服務 -> 查看以IBM開頭的有"cncaitKaifaNode03" 標識的WebSphere服務,重啟.
用如下過濾器不管用.
public class ChartFilter implements Filter{
private String encoding = "UTF-8";
public void init(FilterConfig config) throws javax.servlet.ServletException {
String temp = config.getInitParameter("encoding");
encoding = (temp == null) ? encoding : temp;
}
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain ) throws java.io.IOException, javax.servlet.ServletException {
System.out.println("-----------過濾器-----------encoding = " encoding);
request.setCharacterEncoding(encoding);
response.setCharacterEncoding(encoding);
response.setContentType("text/html; charset=" encoding);
chain.doFilter(request, response);
}
public void destroy() {
}
}
(三)共同問題:
Tomcat 5 和 webSphere6.1 對get請求,如果有奇數個漢字的參數,則緊接著&的下一參數會追加在這個漢字參數后.如:
String url = "/cnca/servlet/update.action?orgName=中國船級社質量認證公司&oscYM=2009-06" ,則取得orgName的值
為中國船級社質量認證公oscYM=2009-06,而oscYM 沒有取到值.
解決的簡單方法就是在 orgName=中國船級社質量認證公司之後 &oscYM=2009-06之前加一個全形空格.
---------------------------------------------------------------
程序從tomcat遷移至websphere的修改
1.普通應用部署在websphere上中文亂碼問題
解決:管理控制台--->伺服器--->應用程序伺服器--->server1--->java和進程管理--->進程定義--->java虛擬機--->將通用jvm參數設置為:
根據你的jsp java文件的編碼是什麼而定,如果是UTF-8 則設置為 -Ddefault.client.encoding=UTF-8 -Dclient.encoding.override=UTF-8 -Dfile.encoding=UTF-8 -Duser.language=zh -Duser.region=CN
2.修改hibernate.cfg.xml (針對我的項目cnca(自律))
<property name="connection.datasource">jdbc/cncaprod</property>
以下下是網上搜集的:
在部署文件中設定了jdbc引用名jdbc/sample,jndi名字為jdbc/sample
如果採用如下代碼:
javax.sql.DataSource ds = (javax.sql.DataSource)ctx.lookup("java:comp/env/jdbc/sample");
conn = ds.getConnection();
運行就報錯:05-7-1 10:02:24:178 CST] 00000031 SystemErr R Naming-Exception: Exception occurred while the JNDI NamingManager was processing a javax.naming.Reference object.
去掉"java:comp/env/」就好了.
解決:確認部署后在概要表空間下的configcellsCN7642012HNode01Cellapplications目錄下相應應用的web.xml文件下有正確的配置JNDI,如:
<b><resource-ref id="ResourceRef_1097466019938"></b>
<res-ref-name>jdbc/yjjndi</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
再查看同目錄下的ibm-web-bnd.xmi文件中id是否和上面的id相同,如下(注意粗體部分):
<b><resRefBindings xmi:id="ResourceRefBinding_1097466019938" jndiName="jdbc/yjjndi" loginConfigurationName="DefaultPrincipalMapping">
<bindingResourceRef href="WEB-INF/web.xml#ResourceRef_1097466019938"/></b>
<properties xmi:id="Property_1165956970219" name="com.ibm.mapping.authDataAlias" value="CN7642012HNode01/yjj2c" description="description"/>
</resRefBindings>
3. 對get請求,去掉類似new String(username.getBytes("iso-8859-1」), "GBK"); 的代碼段.
[火星人 ] Tomcat和Websphere的區別已經有1225次圍觀