原来项目里只有hibernate,没有struts2和spring,用Filter处理汉字编码都正常,页面编码用的是GB18030,Filter的encoding也是GB18030。
但是最近打算引入struts和spring,发现编码的问题就出来了。不管用不用SetCharacterEncodingFilter,页面GB18030传进来的汉字在Action里面都是乱码,如果页面是utf-8就正常,也就是说SetCharacterEncodingFilter不生效。
如果是新工程那全部用UTF-8也无妨,但是原来的工程好多jsp,都从GB18030改成UTF-8工作量太大了。
请教解决办法!
刚刚试了下,如果页面和encoding都是GB18030,只有一种情况编码正常,就是在SetCharacterEncodingFilter设置编码的代码结束以后进入Struts2的拦截器之前的任何Filter里,request.getParameter("m")搞一下,到Action里就正常,没有这句就乱码,这个是什么原因?
解决了,在web.xml的org.apache.struts2.dispatcher.FilterDispatcher里给他指定编码就行了,貌似默认是按照UTF-8编码的。
分数给帮我解答上面这个问题的人,为什么在不指定FilterDispatcher的编码的时候,request.getParameter("m")搞一下也会正常?
另外org.apache.struts2.dispatcher.FilterDispatcher已经不推荐使用了,你已经是从很老的例子里面抄过来的,struts2的核心过滤器已经拆分成三个了org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter、org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter、org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter,FilterDispatcher相当于StrutsPrepareAndExecuteFilter,StrutsPrepareFilter主要用来封装参数给struts2的标签使用,StrutsExecuteFilter才是执行action的,有些页面没有经过action但是也使用了struts2的标签就可以使用StrutsPrepareFilter进行过滤
ssh组合之后,有很多类似filter的实现方式。
If the client hasn’t set character encoding and the request data is encoded with
a different encoding than the default as described above, breakage can occur. To
remedy this situation, a new method setCharacterEncoding(String enc) has
been added to the ServletRequest interface. Developers can override the
character encoding supplied by the container by calling this method. It must be
called prior to parsing any post data or reading any input from the request. Calling
this method once data has been read will not affect the encoding.
这个servlet规范里面里面的说明,setCharacterEncoding方法要在任何request内容读取之前被调用,而struts2的filter是会把所有的request参数封装到ognl的上下文中的,参考这个方法org.apache.struts2.dispatcher.Dispatcher.createContextMap
....
// parameters map wrapping the http parameters. ActionMapping parameters are now handled and applied separately
Map params = new HashMap(request.getParameterMap());
...
解决这个问题的方法就是把编码集过滤器配置在第一个,并且调用request.getParameter("***");固化编码
不是值不一样,而是request内容在被解析的时候会使用setCharacterEncoding指定的字符集进行解码,一旦读取后再调用setCharacterEncoding就不起作用了(Calling
this method once data has been read will not affect the encoding),为了安全期间在字符集过滤(这个过滤器配置在第一个)setCharacterEncoding立马读取使之后的其他程序调用setCharacterEncoding时失效,当然不这样做也可以,你能确保其他程序没有调用setCharacterEncoding就行了。
你的问题在于字符集过滤器没有配置为第一个过滤器,而是在struts2过滤器之后,struts2过滤器会调用new HashMap(request.getParameterMap());来封装参数到ognl上下文中,不知道我说的你明白没有
当struts2过滤器执行之后你的字符集过滤器早已经失效了
当然struts2也是考虑过字符集的问题的,所以它可以在classpath中指定一个struts.properties文件配置struts.i18n.encoding=utf-8来指定字符集,这个时候是不需要其他字符集过滤器的
jsp页面的GBK编码用eclipse的替换功能替换成UTF-8 我以前也改过,java类得, 我自己写了个工具类转换成UTF-8编码。 js和css也转了。