对于大多数从事Java开发的程序员来说,Java中的中文乱码是个很头痛的问题。在Web开发中尤为凸显,明明在页面中输入的是中文,为什么在数据库中保存的却是不是中文,而是我们看不懂的文字。用程序中专业的术语来说,是乱码,不是我们所想要的结果。那么这个问题应该怎么来解决呢?
在做HTML页面时,为了统一页面中不会出现中文乱码问题,我们就把在<head></head>标签中<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />的charset改为GBK或者是gb2312。这是在HTML中的应用,我当时记得授课老师只是提了一下,说要把charset改为GBK或者gb2312即可,这是一个中文的编码格式。当然,可能在这里谈HTML与Java好像没有关系,不过在Java中,解决中文乱码问题也是把字符编码格式改为GBK或者gb2312即可。不过,一般都改为GBK,改为gb2312的很少,我也没有用过,但是效果却是一样的。
在Java中,有一个过滤器的概念。Java的类库中,Java的开发者已经写好了这个接口。我们只需要去实现这个接口,把接口中的方法写好即可。现在,就用过滤器来解决中文的乱码问题。
首先,在Java的Web工程下建一个包,我在此把名字取为com.aptech.jb.epet.filter。在这个包里面建一个普通的Java类,这个类要实现一个javax.servlet.Filter包下的Filter接口。里面有3个方法,分别是destroy()、doFilter()和init()。其中先不管其中的destroy()和init()方法,先看doFilter()方法。在这三个方法中,除了第一个方法没有参数外,其它两个方法都是有参的。
如图所示:
其中,doFilter()方法中,ServletRequest、ServletResponse、FilterChain中原来的参数名不是request、response和chain,只是我们把参数名改了而已。ServletRequest、ServletResponse、FilterChain只是参数类型,把前面两个参数名改为request、response是因为这两个是JSP中的内置对象。在JSP开发中经常使用。然后在方法体中写两名句代码即可解决中文乱码问题,如图中所示。当然,在其中也会有IO和Servlet异常,我们只需用throws关键字要把它抛出即可。
在写好了这个过滤器类后,也不就万事大吉了。重新部署运行后乱码还是没有解决,是什么原因呢?写好这个类后,不要忘了,还要在Web项目中web.xml文件中配置,这样过滤器才真正实现了解决乱码的功能。
在web.xml中配置如图所示:
在这里,有几点要说明一下。在<filter></filter>节点下的<filter-name></filter-name>节点中,这里要给过滤器取个名字,这个名字可以随心所欲的取,不过也要注意命名的规范,在上一章中我已经谈到了关于命名规范的问题;<filter-class></filter-class>节点中,这里要指定过滤器所在的位置,也就是刚才我们定义的那个地方。不过此时要特别注意,路径中一定要包名+类名。如果不是,那么在运行时系统找不到过滤器类,过滤器也不会起作用。而后在<filter-mappin></filter-mappin>节点下的<filter-name></filter-name>节点中,这个名字一定要和前面<filter></filter>节点下的<filter-name></filter-name>节点所取的名字一定要相同。如果不同,过滤器也不会起作用。最后是访问路径的问题,在<url-patten></url-patten>节点中配置为/*,表示以每一次请求都会被这个过滤器所拦截。若是字符,则转换为中文。这样,Web开发中Java的中文问题就解决了,在运行系统时就不会出现乱码了。
前面提到的destroy()和init()方法,我也没有太多的研究,暂时也不知道它有什么作用,只管doFilter()方法配好即可。
在学习Servlet技术时,也学习了一下解决中文乱码问题的方法。即是在Servlet的doPost()或者doGet()方法中,增加一句request.setCharacterEncoding("GBK"); 的代码即可。不过,个人认为这种方法不可取,在稍有点规模的项目中,有很多Servlet,只要有添加功能的Servlet,就要写这句代码,那么意味着要写很多重复的代码,这也违反了Java的开闭原则。在此时,建议使用过滤器,这样需写一次代码就解决了乱码问题。对比一下,你会选择哪一种呢???