Posted on 2006-03-02 11:17
么么茶 阅读(11117)
评论(2) 编辑 收藏 所属分类:
JAVA-WEB
今日无意中发现在中文系统使用良好的中文页面在移植到英文系统后出现了乱码,多方查找发现,出现乱码的页面是使用的jstl标签的c:url和c:param标签生成的URL通过c:import嵌入网页的,所以怀疑可能是c:param在进行Base64编码是使用的编码有问题。通过查找JSTL的源码发现在org.apache.taglibs.standard.tag.common.core.ParamSupport类即c:param的实现类中有这样一行代码:
parent.addParameter(URLEncoder.encode(name), URLEncoder.encode(value))
其中URLEncoder.encode是问题所在。在JDK的API文档中已经标明URLEncoder.encode(String)这个方法已经deprecated了,而应该在编码时指定编码字符集。找到这里之后,再来看看URLEncoder.encode(String)的实现:
public static String encode(String s){
String str = null;
try {
str = encode(s, dfltEncName);
} catch (UnsupportedEncodingException e) {
}
return str;
}
可以看到默认使用了dfltEncName的字符集,那么这个dfltEncName又是如何得到的呢?从源码中找到如下:
dfltEncName = (String) AccessController.doProivileged(new GetPropertyAction("file.encoding"))
看到这里就一目了然了,JVM是从系统变量file.encoding中读取了默认编码的字符集。
之后,写了一个简单的测试程序,分别从中英文系统中取了一次默认的字符集,中文没问题是GBK,但是英文的就很奇怪,居然是Cp1252(好像是Latin I,按说应该是ISO8859-1才是)。看了一下英文系统的区域设置,Location选的是Englist(United States),改成PRC就完事大吉了。
为了防止这种问题的发生,最后还是决定采用最保险的办法,在Tomcat的启动参数中加入-Dfile.encoding=GBK,强制将缺省的字符集设为GBK,这样就一劳永逸了。