感谢: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. 通过一个Thinkphp完成多个项目

    1.单独取压缩包中的Thinkphp文件夹 2.在单独的项目内创建一个引入文件 3.通过浏览器访问该index.php 会创建相应的目录

  2. Git 的安装和创建版本库 。

    Git 的优点就不再多说了 .直接进入正题吧 . 安装Git 首先可以尝试输入 Git 看看有没有反映 . $ git The program 'git' is currently not insta ...

  3. React Native 组件之Image

    Image组件类似于iOS中UIImage控件,该组件可以通过多种方式加载图片资源. 使用方式,加载方式有如下几种: /** * Sample React Native App * https://g ...

  4. Minimum Inversion Number_线段树||树状数组

    Problem Description The inversion number of a given number sequence a1, a2, ..., an is the number of ...

  5. DIV+CSS设计IE6浮动产生双倍距离

    <!doctype html><html><head> <meta name="Keywords" content="" ...

  6. 锋利的jquery学习笔记

    1.$("#tt")获取的永远都是一个jquery对象,所以要判断页面上是否存在某个对象不能像js中 if($("#tt")){ } 而是通过: ){ } ps ...

  7. 【题解】【位操作】【Leetcode】Single Number II

    Given an array of integers, every element appears three times except for one. Find that single one. ...

  8. dedecms 蜘蛛抓取设置 robots.txt

    我们可以用robots.txt屏蔽蜘蛛文件来跟蜘蛛来达成一个协议,但现在很少注重,其实用好robots.txt屏蔽蜘蛛文件,能给你的网站提高权重,接下来重庆SEO讲一下robots.txt屏蔽蜘蛛文件 ...

  9. 尽量多的以 const/enum/inline 替代 #define

    前言 在面向过程语言,如 C 语言中,#define 非常常见,也确实好用,值得提倡.但在如今面向对象的语言,如 C++ 语言中,#define 就要尽量少用了. 为何在 C++ 中就要少用了呢? 这 ...

  10. Java多线程的实现

    记得面试的时候,面试官问了Java多线程实现的方式有几种,它们之间的区别是什么?作为一个Java新手,将最近的学习总结如下: 1.Java多线程实现方式 Java多线程实现方式主要有三种:继承Thre ...