感谢:http://blog.csdn.net/heidan2006/article/details/3075730

很简单很实用的一个过滤器,当前台JSP页面和JAVA代码中使用了不同的字符集进行编码的时候就会出现表单提交的数据或者上传/下载中文名称文件出现乱码的问题,那这个类就可以出场了。

        从名字就可以看出来它是个过滤器了,所以就要想配置普通过滤器那样配置到web.xml中去了,配置方式如下:

  1.         <filter>
  2.                 <filter-name>encodingFilter</filter-name>
  3.                     <filter-class>
  4. org.springframework.web.filter.CharacterEncodingFilter
  5.                     </filter-class>
  6.                 <init-param>
  7.                     <param-name>encoding</param-name>
  8.                     <param-value>UTF-8</param-value>
  9.                 </init-param>
  10. <init-param>
  11.                     <param-name>forceEncoding</param-name>
  12.                     <param-value>false</param-value>
  13.                </init-param>
  14.         </filter>
  15.         <filter-mapping>
  16.                 <filter-name>encodingFilter</filter-name>
  17.                 <url-pattern>/*</url-pattern>
  18.        </filter-mapping>

        和普通过滤器配置没什么区别,就是多了两个初始化参数,两个参数的作用分别是:

    encoding----->用来指定一个具体的字符集

    forceEncoding------->Spring的早期版本这个参数作用很单一,当request中已经被指定了一个字符集的时候是否再将用endcoding对应的字符集设置到request中去。举个例子来说明,假如说过滤器就像上面那样被配置到web.xml了,当请求被提交之后,过滤器会判断request.getCharacterEncoding()是否为null,如果是null那么就会进行request.setCharacterEncoding("UTF-8")的操作,如果不是null那么过滤器什么也不会做。

    不过Spring目前得版本这个类的代码已经被重构了,代码更加“漂亮”了,这个参数的作用也发生了细微的改变。

    为了加深印象从源码来分析一下这个参数的变化。

    首先,说明 一下CharacterEncodingFilter是继承OncePerRequestFilter抽象类而来的,OncePerRequestFilter实现了doFilter方法:

  1. public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
  2.    throws ServletException, IOException {
  3.          ...........
  4.          ...........
  5.       String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
  6. if (request.getAttribute(alreadyFilteredAttributeName) != null || shouldNotFilter(httpRequest)) {
  7.            filterChain.doFilter(request, response);
  8.       }
  9. else {
  10.            request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
  11. try {
  12.             doFilterInternal(httpRequest, httpResponse, filterChain);
  13.            }
  14. finally {
  15.             request.removeAttribute(alreadyFilteredAttributeName);
  16.            }
  17.       }
  18. }
  19. public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";(在OncePerRequestFilter中定义的常量)

说明:

1. getAlreadyFilteredAttributeName()方法返回的字符串是="我们给filter配置的名字+ALREADY_FILTERED_SUFFIX",所以request请求第一次到达过滤器的时候request.getAttribute(alreadyFilteredAttributeName) 值一定是null ,shouldNotFilter(httpRequest)方法默认实现始终返回false(这个方法也可以在子类中进行扩展);

2. 当request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE)之后就会执行doFilterInternal(httpRequest, httpResponse, filterChain);方法了,doFilterInternal这里是个抽象方法,它是在子类CharacterEncodingFilter中被实现的,实现如下:

  1. protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
  2.    throws ServletException, IOException {
  3. if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
  4.                 request.setCharacterEncoding(this.encoding);
  5. if (this.forceEncoding && responseSetCharacterEncodingAvailable) {
  6.                     response.setCharacterEncoding(this.encoding);
  7.                    }
  8.               }
  9.               filterChain.doFilter(request, response);
  10.   }
  11. private final static boolean responseSetCharacterEncodingAvailable = ClassUtils.hasMethod(
  12.    HttpServletResponse.class, "setCharacterEncoding", new Class[] {String.class});

说明:

1. 静态常量responseSetCharacterEncodingAvailable 是通过反射来判断response是否有setCharacterEncoding方法,返回值应该都是true.

2. this.encoding != null :当encoding初始化参数被指定时条件满足。

3. (this.forceEncoding || request.getCharacterEncoding() == null )==true:当forceEncoding初始化参数设置为true或者request已经被指定了一个字符编码的时候条件满足。

如果没记得错,Spring早期版本这个方法得实现应该是:

  1. protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
  2.    throws ServletException, IOException {
  3. if (this.forceEncoding || request.getCharacterEncoding() == null) {
  4.                    request.setCharacterEncoding(this.encoding);
  5.               }
  6.               filterChain.doFilter(request, response);
  7.   }

参数forceEncoding的作用很明显了吧!以前只是对request字符编码起作用,现在如果将forceEncoding设为true也会影响到response中的字符编码,通常这个是我们不希望的。

总结:

1.  OncePerRequestFilter这个抽象过滤器很好的实现了对每个request只执行一次过滤操作,如果有类似的需求可以继承该类并实现doFilterInternal方法来完成。

2.  CharacterEncodingFilter类可以通过简单配置来帮我们实现字符集转换的功能。另外多说一句,如果采用Struts2.0的MVC框架我个人感觉中文问题已经不是问题了,可以通过配置struts.i18n.encoding常量来实现统一字符编码。

org.springframework.web.filter.CharacterEncodingFilter的更多相关文章

  1. java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterEncodingFilter

    今天在用git merge 新代码后报了如下错误:java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterE ...

  2. 通过org.springframework.web.filter.CharacterEncodingFilter定义Spring web请求的编码

    通过类org.springframework.web.filter.CharacterEncodingFilter,定义request和response的编码.具体做法是,在web.xml中定义一个F ...

  3. java.lang.ClassCastException: org.springframework.web.filter.CharacterEncodingFilter cannot be cast to javax.servlet.Filter

    java.lang.ClassCastException: org.springframework.web.filter.CharacterEncodingFilter cannot be cast ...

  4. SpringMVC------报错:java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterEncodingFilter

    详细信息: java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterEncodingFilter 严重: E ...

  5. java.lang.ClassCastException: org.springframework.web.filter.CharacterEncodingFilter cannot be cast

    严重: Exception starting filter encodingFilterjava.lang.ClassCastException: org.springframework.web.fi ...

  6. 关于org.springframework.web.filter.CharacterEncodingFilter的学习

    介绍 org.springframework.web.filter.CharacterEncodingFilter 这是一个过滤器,是Spring在web请求中定义request和response的编 ...

  7. Eclipse中maven项目报错:org.springframework.web.filter.CharacterEncodingFilter

    写了一个demo,发现在tomcat中部署完项目,启动时报错. 1,问题描述 2,解决办法 1)程序在部署完成后报错,说明是程序是编译通过的,即编译编译路径Java Build Path没问题.2)此 ...

  8. Maven项目启动报错:org.springframework.web.filter.CharacterEncodingFilter cannot be cast to javax.servlet.Filter

    看网上说法tomcat启动时会把lib目录下的jar包加载进内存,而项目里也有相同的jar包就会导致jar包冲突 解决办法: 把pom依赖里相应的jar包添加<scope>标签 <d ...

  9. 'org.springframework.web.filter.CharacterEncodingFilter' is not assignable to 'javax.servlet.Filter,This inspection lets you spot the following problems that might occur in descriptors that are used t

    1.jar包导入错误,因为maven下载的原因: 删除这样的包,然后让maven重新下载,问题就会解决

随机推荐

  1. bistu新生-1005

    #include "stdio.h"#include "string.h"int main(){ char ku[]={'0','1','2','3','4', ...

  2. iOS 开发之推力动画效果

    步骤: 1.使用single view application 创建新的项目 2.在.h文件中需要遵守两个协议<UICollisionBehaviorDelegate,UIGestureReco ...

  3. 【LeetCode OJ】Best Time to Buy and Sell Stock

    Problem Link: http://oj.leetcode.com/problems/best-time-to-buy-and-sell-stock/ We solve this problem ...

  4. Java 解惑:Random 种子的作用、含参与不含参构造函数区别

    Random 通常用来作为随机数生成器,它有两个构造方法: Random random = new Random(); Random random2 = new Random(50); 1.不含参构造 ...

  5. 破解 keyme2程序(固定明码比较)

    系统 : Windows xp 程序 : keyme2 程序下载地址 :http://pan.baidu.com/s/1pKqlHiF 要求 : 找出序列号 使用工具 : IDA Pro & ...

  6. mysql的ERROR:1042

    在虚拟机上测试数据库备份功能,需要连接外部机器上的mysql,pdo总是报超时错误! 起初认为是用的mysql账号的域不匹配!后来发现不是因为这个! 在终端中用mysql命令尝试连接,发现返回的错误是 ...

  7. 修正magento快速搜索返回结果不准确

    有时候发现用magento的mini 快速搜索搜出来的结果一点都不准确,跟实际结果相差甚大,这里发现修改一个地方即可修复这个问题. 打开app/code/core/Mage/CatalogSearch ...

  8. AWK处理日志入门(转)

    前言 这两天自己挽起袖子处理日志,终于把AWK给入门了.其实AWK的基本使用,学起来也就半天的时间,之前总是靠同事代劳,惰性呀. 此文仅为菜鸟入门,运维们请勿围观. 下面是被处理的日志的示例,不那么标 ...

  9. windows下apache及mysql定时自动重启设置

    有时候觉得,服务器运行时间过长,造成服务器内存等压力过大.因此,不用重新启动服务器的情况下,完成apache和mysql的内存释放,是非常有益处的(把重启时间设置在访问量最低的).首先,apache的 ...

  10. Spring的声明试事务

    1 在配置文件中加入: <!-- 配置事务管理器 --> <bean id="transactionManager" class="org.spring ...