之前其实遇到过fmt:formatDate标签导致页面中文乱码的问题,但是当时是我同事修改了程序解决的,我没有自己研究。昨天需要用到fmt标签了,想起来这个问题,尝试重现了一下,在Resin上是正常的,在WebSphere上是乱码的,于是就研究研究吧。
由于历史原因,我们现在使用的软件产品、开源框架都比较旧,列在下面:
J2EE Web: 2.3
JSTL: 1.0.6, 需要JSP 1.2 的Web容器支持
生产环境:JDk 1.4.2, WebSphere: 5.1.1.19,支持Servlet 2.3, JSP 1.2, EJB 2.0
开发环境:JDK 1.5.0(javac时编译为1.4版本), Resin: 3.2.1
文件编码及页面ContentType中的编码:UTF-8
首先,使用Fiddler跟踪一下,发现页面响应的编码不再是我在页面设置的UTF-8了,而是变成了GB13080。根据JSTL的说明文档,很多fmt标签都会调用fmt:setLocale,比如fmt:formatDate, fmt:formatNumber等。而fmt:setLocale会通过调用ServletResponse.setLocale方法来设置响应的Locale。在Servlet 2.3规范中,设置响应的Locale会影响页面的编码,同时规范中也说到,如果调用ServletResponse.setContentType,并且在参数中指明charset,那么会使用charset去覆盖由于ServletResponse.setLocale导致的编码。
问题的原因比较清楚了,解决办法有这么几种
1. 在调用了fmt标签之后,通过response.setContentType("text/html; charset=UTF-8");来重设页面编码。但是这是不现实的,也是很傻的
2. 使用Filter设置Response的编码。比如org.springframework.web.filter.CharacterEncodingFilter。Sorry,Servlet 2.3规范中,仅有getCharacterEncoding(),没有setCharacterEncoding。所以在org.springframework.web.filter.CharacterEncodingFilter的代码中,有一个静态变量,就是用来检测Web容器是否提供setCharacterEncoding编码的:
private final static boolean responseSetCharacterEncodingAvailable = ClassUtils.hasMethod(
HttpServletResponse.class, "setCharacterEncoding", new Class[] {String.class});
3. 设置Locale和编码的对照。还是不行,因为从Servlet 2.4 才开始提供Locale和编码的映射关系,在web.xml里面:
<locale-encoding-mapping-list>
<locale-encoding-mapping>
<locale>ja</locale>
<encoding>Shift_JIS</encoding>
</locale-encoding-mapping>
</locale-encoding-mapping-list>
方法1太傻,即使它能解决这个问题,也不能真的用这种方法;方法2和方法3在我们现在环境中不支持。
所以,最后,放弃了fmt,使用Struts的bean:write。
JSTL,挺好的东西,俺只有望洋兴叹的份了~~~
posted on 2009-07-22 22:27
YODA 阅读(4091)
评论(3) 编辑 收藏