以下總結這段時間以來遇到的中文問題匯集:
注:以下“后臺”字眼,相當于在servlet內,或者某一個類內,或者struts的action內。
1.一字符串在后臺用system.out.println輸出正常,保存在session里到JSP頁面顯示亂碼
最初的亂碼問題.
原因:似乎是默認的JSP頁面采用8859-1編碼,顯示不了中文。
解決:在JSP頁面上方加個<%@ page contentType="text/html;charset=utf-8"%>解決。當然,也可以用charaset="gbk","gb2312"之類的編碼,不過建議還是用utf-8,詳細原因去看看jdon板橋里人的那篇《中文亂碼終極解決方法》。
*****************************************************************************
2.提交表單,在后臺讀取表單內容發現亂碼
原因:request的默認編碼問題,具體不甚清楚,沒看過tomcat源代碼。。。
解決:寫個fileter,具體如下:
package operator;
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;
public class SetCharacterEncodingFilter implements Filter {
protected String encoding = null;
protected FilterConfig filterConfig = null;
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
public void destroy() {
this.encoding = null;
this.filterConfig = null;
}
protected String selectEncoding(ServletRequest request) {
return (this.encoding);
}
}
web.xml配置:
在servlet-mapping后加入以下內容:
<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>operator.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
***********************************************************************
3.下載時,“另保存為”默認名字顯示亂碼
原因:不清楚。。。
在tomcat安裝目錄的config/sever.xml內的
<Connector
port="80" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="UTF-8" />
加進最后的“URIEncoding="UTF8"
4.在后臺用system.out.println()輸出正常,保存到mysql數據庫EMS顯示亂碼,讀回數據也是亂碼
原因:mysql默認采用的是latin1編碼;
解決:創建表的時候要修改成utf-8。如果已存在表,用EMS的話,直接修改table-property里面的default charater set就可以了,其他管理工具不知道,沒用過。
5.在后臺用system.out.println()輸出正常,保存到mysql數據庫EMS顯示亂碼,讀回數據時——居然正常了,直接往數據庫里插入正常的中文,讀出——居然亂碼了;
原因:EMS管理工具的默認顯示問題
解決:register數據庫時,client default charater set改utf-8
注:這該死的問題困擾了我好長一段時間,一直以為我程序有問題,檢查了N久,發現居然是工具顯示問題。。
6.COMMON-UPLOAD 上傳中文名文件時,顯示亂碼
原因:common-upload組件默認采用系統的編碼,而頁面傳過來的請求采用UTF-8編碼。
我的系統是簡體中文WINDOWS 2K3,系統編碼是GBK,當頁面請求過來時,UPLOAD就把UTF8編碼的流直接按GBK編碼了。。。如果用new String(oldStr.getBytes("gbk"),"utf8)可以發現,部分中文可以還原回去。
解決:網上的說法五花八門,甚至有歸罪于這是UPLOAD的BUG,其實只要在
DiskFileUpload fu = new DiskFileUpload();
后加一句:
fu.setHeaderEncoding("utf8");
就解決了。。。
看來有時候還是直接讀英文幫助手冊來得正確。。。
問題描述:
在inputtext中輸入中文,然后在輸出,顯示為亂碼。
解決方法:
1、自定義轉器
package util;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.convert.Converter;
import javax.faces.context.FacesContext;
import javax.faces.convert.ConverterException;
public class StringConverter implements Converter {
public Object getAsObject(FacesContext context, UIComponent component,
String newValues) throws ConverterException {
String newstr = "";
if (newValues == null) {
newValues = "";
}
byte[] byte1 = null;
try {
byte1 = newValues.getBytes("ISO-8859-1");
newstr = new String(byte1, "GB2312");
UIInput input=(UIInput)component;//
input.setSubmittedValue(newstr);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return newstr;
}
public String getAsString(FacesContext context, UIComponent component,
Object Values) throws ConverterException {
return (String) Values;
}
}
2、注冊轉換器
faces-config.xml片段
<converter>
<converter-id>stringconverter</converter-id>
<converter-class>util.StringConverter</converter-class>
</converter>
3、在頁面使用轉換器
<h:inputText id="account" value="#{util.account}" required="true" styleClass="input" >
<f:converter converterId="stringconverter"/> <!--注:這里不是EL表達式-->
JSF估計是天生就是這個毛病,凡是有jsf標簽生成的html代碼中有中文的(指從 backbean中提取出來的),在html源代碼中回出現類似:雨滴 這種“漢字內碼”,比如jsf的代碼如下:
<f:view>
<h:outputText value="#{testBean.testValue}"></h:outputText>
<br>
哈哈
</f:view>
<br>呵呵
瀏覽器顯示如下:
雨滴雨滴2
哈哈
呵呵
而查看html源代碼如下:
雨滴雨滴2 <br> 哈哈 <br>呵呵
我們發現用jsf標簽出來的有內碼,而不是jsf標簽的就沒事。(網頁服務器編碼等都是UTF-8統一的)。
那么有什么辦法呢?
第一個方法,寫一個自定義的Converter,在jsf中有這種功能,但是我測試了寫了一個converter,但是效果令我失望,因為我發現jsf的內在邏輯把漢字變成內碼的地方在converter以后,我在converter中添加什么東西,在html源代碼中還是內碼。于是放棄
第二種方法是在寫個Servlet的Filter過濾器,放到web.xml中,但是由于漢字內碼雨需要去掉前后墜,然后把這幾個數字變成char,在變成String。每個字都用這種方法變回來,這樣本身效率回很低,而且一個html文檔中用jsf顯示的內容占有比率有多有少,如果沒有標簽的也是用這個過濾器一個字一個字取解析,那么效率就更不敢恭維了。雖然這種方法一定可行(因為過濾器可以到輸出的最后一步),但是由于效率問題,我沒有取試。
第三種方法是我自己研究出來的,通過FacesContext類來作,方法如下:
首先,寫一個類
public class Converter {
public static void process(String str){
FacesContext fc=FacesContext.getCurrentInstance();
try {
fc.getResponseWriter().write(str);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
然后在每個backbean中需要getXXX方法中返回是String的方法中修改如下:
把 return XXX 改為 return ""
在return前面,也就是方法的最后一步,添加Converter.process(testValue),這個testValue是你要return的變量
ok,就這么簡單^_^。。。
在網上找了一天沒找到合理解決方法,用這個方法終于解決了。。