使用PrintWriter对象导致Struts国际化失败问题的解决及分析
1.Struts国际化的要求
1.1设置字符编码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html:html lang="true">
1.2将图片、文字、按钮国际化
使用<bean:message>标签,和资源文件
1.3创建资源文件
创建默认资源文件
创建临时中文资源文件,然后使用native2ascii -encoding gb2312 oldfile newfile生成中文资源文件
创建英文资源文件
需要注意的是:在中文winxp和windows2000上,中文资源文件为默认资源文件,
例如:如果没有英文资源文件,选择语音编码为en-gb,将显示中文界面;而当选择任何其他语言编码时,都显示中文界面
1.4采用Servlet过滤器设置请求数据的字符编码
设置为UTF-8,代码略,网上到处都有
2.无法国际化的应用的现象
2.1在完成上述步骤以后,执行一个测试应用,发现中文都是???,而获取请求的编码(request.getCharacterEncoding()),发现仍然是UTF-8,查看页面编码,为GB2312,而正确的页面编码应该是UTF-8
2.2在使用System.out.println()时,输出的中文是正确的,这表明在输出给JSP页时,转码发生了问题
2.3如果直接运行JSP文件,可以显示中文,但如果通过Action forward过来,就会变成???。
这样,就说明Action文件有问题
3.问题的发现与解决
仔细查看自己编写的Action文件,发现其中有一条
PrintWriter out=response.getWriter();
注释掉这条或者在前面加上response.setCharacterEncoding("UTF-8");都可以解决问题
4.分析
修改代码为PrintWriter out1=response.getWriter();
仍然会发生中文乱码问题,查看相关java文档,个人分析如下:
4.1jsp页面输出时会使用Action中定义的out或out1,因为JSP隐含对象out也是一个response对象,如果定义了PringWriter对象,那么JSP隐含对象也会使用这个自定义的out,导致无法中文化。
4.2在Action中使用response.getCharacterEncoding();发现字符编码为ISO-8859-1
而使用PrintWriter对象时,字符编码没有制定的话,编码也设置为ISO-8859-1
Action中的数据编码会通过过滤器设置为UTF-8,但PrintWriter对象中的数据无法过滤,因此显示为乱码
4.3JSP文件的字符编码设置为了UTF-8,因此PrintWriter对象中的数据使用UTF-8解码显示,当然会是乱码,此时,将数据按UTF-8编码,再按iso8859-1解码,就可以显示出中文,即:
<%
//代码只用于测试,实际开发中,不应该在JSP中直接写java代码
String s = (String)request.getAttribute("xxx");
out.println(new String(s.getBytes("UTF-8"),"iso8859-1");
%>
此时显示的仍然为乱码,但不再是???,而是正确的的UTF-8编码,选择浏览器编码为Unicode(UTF-8)可以正常显示中文了。