`

CharacterEncodingFilter类的学习(转)

阅读更多
     我的第一篇正式BLOG就写点简单的东西吧,记录一下CharacterEncodingFilter这个类的使用和作用。

        很简单很实用的一个过滤器,当前台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.
  16.         <filter-mapping>
  17.                 <filter-name>encodingFilter</filter-name>
  18.                 <url-pattern>/*</url-pattern>
  19.        </filter-mapping>
20.

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

    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.
   6.          ...........
   7.
   8.       String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
   9.       if (request.getAttribute(alreadyFilteredAttributeName) != null || shouldNotFilter(httpRequest)) {
  10.
  11.            filterChain.doFilter(request, response);
  12.       }
  13.       else {
  14.            request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
  15.        try {
  16.             doFilterInternal(httpRequest, httpResponse, filterChain);
  17.            }
  18.        finally {
  19.
  20.             request.removeAttribute(alreadyFilteredAttributeName);
  21.            }
  22.       }
  23.  }
  24.
  25. public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";(在OncePerRequestFilter中定义的常量)
26.

说明:

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.
   4.          if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
   5.                 request.setCharacterEncoding(this.encoding);
   6.                if (this.forceEncoding && responseSetCharacterEncodingAvailable) {
   7.                     response.setCharacterEncoding(this.encoding);
   8.                    }
   9.               }
  10.               filterChain.doFilter(request, response);
  11.   }
  12.
  13. private final static boolean responseSetCharacterEncodingAvailable = ClassUtils.hasMethod(
  14.    HttpServletResponse.class, "setCharacterEncoding", new Class[] {String.class});
15.

说明:

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.
   4.          if (this.forceEncoding || request.getCharacterEncoding() == null) {
   5.                    request.setCharacterEncoding(this.encoding);
   6.               }
   7.               filterChain.doFilter(request, response);
   8.   }
9.

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

总结:

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

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

说明:所写内容纯属个人理解和认识,如有理解偏差希望有热心的朋友可以指出,如有描述有含糊不清的地方希望可以和你得到沟通和交流!
分享到:
评论

相关推荐

    学习了servlet之后,将servlet全部整合在一个工具类中

    在描述中提到的过滤器部分,可能包含自定义的过滤器实现,如`CharacterEncodingFilter`,用于统一设定请求和响应的编码为UTF-8。 2. **反射技术(Reflection)**:反射是Java的一个强大特性,允许程序在运行时检查...

    SpringMVC第一天学习代码

    在第一天的学习中,你将接触到一系列关键概念和技术,这些内容将帮助你理解和应用SpringMVC来构建动态网站。 首先,让我们从入门案例开始。SpringMVC的入门通常涉及创建一个DispatcherServlet,它是SpringMVC的前端...

    SpringMVC 学习总结

    3. 配置 web.xml,设置 DispatcherServlet 作为前端控制器,并定义 CharacterEncodingFilter 来确保请求编码统一。 4. 创建 springmvc-servlet.xml 配置文件,配置组件扫描、视图解析器、处理器映射器和处理器适配器...

    乱码处理操作类

    在IT行业中,乱码问题是一个常见的困扰,尤其是在处理多语言环境或者进行数据传输时。"乱码处理操作类"指的是...对于这个"乱码处理操作类",我们可以通过查看源代码,学习其处理乱码的具体实现,以提升我们的编码技能。

    jsp过滤器(编码)

    在这个例子中,我们定义了一个名为`CharacterEncodingFilter`的过滤器,使用了Spring框架提供的`CharacterEncodingFilter`类。`encoding`参数设置编码格式为`UTF-8`,`forceEncoding`参数设为`true`,表示强制对请求...

    struts学习笔记

    其次,在Servlet容器配置文件中(如web.xml),设置过滤器以处理请求和响应的编码,例如使用`CharacterEncodingFilter`。最后,在Action类中,如果需要对请求参数进行处理,确保在读取或写入时指定正确的字符集。在...

    spring 数据绑定心得,适合新手

    Spring提供了多种方式来解决这个问题,包括在`HttpServletRequest`中设置编码,或者在`WebConfig`中配置全局的字符编码,如`CharacterEncodingFilter`。 在学习过程中,你可能会遇到各种问题,比如绑定失败、空指针...

    struts2 使用action属性接收中文参数(post提交)

    - 为了确保请求的正确编码,可以在web应用的过滤器(Filter)中进行强制转换,比如添加一个字符编码过滤器(CharacterEncodingFilter),并配置为在请求进入Action之前先进行编码转换。 3. **Action类的参数注解**...

    监听器 过滤器 详解

    2. **CharacterEncodingFilter**:设置请求和响应的字符编码,防止乱码问题。 3. **LoginFilter**:实现权限验证,未登录的用户只能访问登录页面。 4. **GzipFilter**:对响应内容进行压缩,提高传输效率。 过滤器...

    struts上传(已解决中文问题)

    3. **文件保存**:在处理上传文件的Action类中,你需要使用正确的字符编码保存文件名。例如: ```java FileItem item = ...; // 获取到的FileItem对象 String fileName = new String(item.getName().getBytes(...

    ssm整合Demo源文件.zip

    1. **ForwardConfig**: Spring MVC提供了`org.springframework.web.servlet.config.annotation.ForwardingConfiguration`类,可以用来配置全局的请求转发规则。 2. **ViewController**: 通过`@RequestMapping`注解...

    JAVA框架面试题汇总编程资料

    Struts2基于类开发,通过类的属性传递请求数据,只能设计为多例模式。 3. **数据处理方式不同**:Struts2使用值栈存储请求和响应数据,通过OGNL表达式进行数据存取;Spring MVC通过参数解析器解析request对象,将...

    使用Jersey框架搭建Rest服务

    通过本文档的学习,我们可以了解到搭建基于Spring与Jersey框架的RESTful Web服务的全过程,包括环境配置、工具选择、项目创建、依赖管理、配置文件编写等多个方面。这些知识点为开发人员提供了从零开始搭建REST服务...

    Java Appfuse-源代码分析-综合文档

    总之,Appfuse 是一个强大而灵活的框架,通过源代码分析,我们可以理解其设计理念,学习如何高效地利用这些技术来构建和维护 J2EE 应用程序。在实际开发中,理解并掌握这些核心概念和机制,将有助于提高开发效率和...

Global site tag (gtag.js) - Google Analytics