1 乱码的困惑:
在使用struts框架时,在页面使用text控件时,如果输入的是中文,当提交表单封装到FromBean中,然后通过Action进行业务逻辑处理的时候,如果要打印出控件值时会出现乱码问题。
2 乱码的原因:
原因在于:提交时的字符编码没有被指定。没有指定字符编码的web服务器总是会使用默认的字符编码来获取提交的参数。一般的字符编码是ISO-8859-1,其属于单字节编码,无法表示中文。
在建立JSP页面时一般头部代码为 <%@ page contentType="text/html; charset=gb2312" %>,这条语句决定了此页面使用GB2312编码形式,而在数据库中一般用的是ISO-8859-1字符集存储数据. 且Java在处理字符时默认采用统一的ISO-8859-1字符集,所以就出现乱码问题。
支持中文的编码有:
GB2312/GBK:汉字的国标码,专门用来表示汉字,是双字节编码。兼容ISO-8859-1编码。其中GBK编码能够同时表示简体和繁体,GB2312只能表示简体。
Unicode/UTF:unicode是最统一的编码,可以表示所有语言的字符,是定长双字节编码。UTF兼容ISO-8859-1编码,也可以表示所有语言的字符,但是UTF编码不是定长编码,每个字符的长度从1到6个字节不等。通常使用UTF编码来实现国际化支持。
3 解决的思路:
第一,既然默认是以ISO-8859-1编码提交,那么只要在获取使用时,以页面展示的字符编码和ISO-8859-1编码之间进行转换即可。
第二,既然默认是以ISO-8859-1编码提交,那么只要将提交的编码方式改成页面展示的字符编码即可。
4 解决的方法:
对于第一种思路:
利用String类的构造器:public String (byte bytes[ ] , String charsetName),将byte类型的参数转换成String类型的编码方式参数所指定的编码。
ActionForm.set%(new String(ActionForm.get%().getBytes("ISO-8859-1"),"GB2312")); //set%,get%是ActionForm中属性%的set和get方法。
通过对每个页面获取的控件值进行编码的转换,可以得到真实的字符串,但是页面的提交参数一旦多了,对每个参数进行转换是很麻烦的。
对于第二种思路:
只需要在提交到的servlet中添加以下内容:request.setCharacterEncoding("***");随后从request中获取的参数都将以"***"所指定的编码方式来进行。如果使用struts框架,则servlet是包含在框架发布包中的,要实现它,则需要继承servlet并提供request.setCharacterEncoding("***")语句。
更好的做法是提供一个Filter,使得在不修改servlet的前提下改变request的编码方式设定。方法:一是在web.xml中定义怎样的响应会进入这个filter,并传递一些初始参数;二是提供一个filter。
<filter> <filter-name>set character encoding</filter-name> <filter-class>***.SetCharacterEncoding<filter-class> <init-param> <param-name>encoding</param-name> <param-value>gb2312</param-value> </init-param> </filter> <filter-mapping> <filter-name>set character encoding</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping>
当所有×.do的请求到来时,都会通过SetCharacterEncodingFilter类来进行过滤的动作,传递给
SetCharacterEncodingFilter类的参数是encoding=“gb2312”。
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;
/**此过滤器会从web.xml中获取encoding参数来装饰request*/ public class SetCharacterEncodingFilter implements Filter { protected String encoding=null; protected FilterConfig filterConfig =null; protected boolean ignore = true; @Override public void destroy() { //撤销所有全局变量的值,置为NULL this.encoding=null; this.filterConfig=null; }
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //从web.xml中得到过滤器的字符串编码 if(ignore || (request.getCharacterEncoding()==null)){ String encoding = selectEncoding(request); if(encoding!=null) request.setCharacterEncoding(encoding);//设置字符串编码 } chain.doFilter(request, response); } @Override public void init(FilterConfig filterConfig) throws ServletException { //初始化方法判断web.xml中过滤器是否传入ignore参数,当ignore参数为yes或true时忽略本过滤器 this.filterConfig = filterConfig; this.encoding = filterConfig.getInitParameter("encoding"); String value = filterConfig.getInitParameter("ignore"); if(value==null) this.ignore=true; else if(value.equalsIgnoreCase("true")) this.ignore=true; else if (value.equalsIgnoreCase("yes")) this.ignore=true; else this.ignore=false; } public String selectEncoding(ServletRequest request){ return (this.encoding); } }