`
liuluo129
  • 浏览: 114905 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring MVC中各个filter的用法

阅读更多

过滤器相关类的结构

spring mvc的org.springframework.web.filter包下的Java文件如下:


类的结构如下:

AbstractRequestLoggingFilter及其子类 

  AbstractRequestLoggingFilter类定义了两个方法beforeRequest和afterRequest分别用于设定过滤前后执行的操作,它有三个子类,分别是CommonsRequestLoggingFilter、ServletContextRequestLoggingFilter和Log4jNestedDiagnosticContextFilter,这三个子类分别实现了各自的beforeRequest和afterRequest。其中,CommonsRequestLoggingFilter在过滤前后分别打印出一段debug的信息;ServletContextRequestLoggingFilter在过滤前后分别向日志文件中写入一段日志信息,日志文件可由log4j.properties等指定;Log4jNestedDiagnosticContextFilter则将日志信息存储到NDC中,NDC采用了一个类似栈的机制来push和pot上下文信息,每一个线程都独立地储存上下文信息,比如说一个servlet就可以针对 每一个request创建对应的NDC,储存客户端地址等信息。

CharacterEncodingFilter

该过滤器是配置编码格式的,在web.xml中设置如下:

<filter>
  <filter-name>springCharacterEncodingFilter</filter-name>
  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  <init-param>
     <param-name>forceEncoding</param-name>
     <param-value>true</param-value>
  </init-param>
  <init-param>
     <param-name>encoding</param-name>
     <param-value>UTF-8</param-value>
  </init-param>
</filter>
<filter-mapping>
   <filter-name>springCharacterEncodingFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

 HiddenHttpMethodFilter

html中form表单只支持GET与POST请求,而DELETE、PUT等method并不支持,spring3添加了一个过滤器,可以将这些请求转换为标准的http方法,使得支持GET、POST、PUT与DELETE请求。可以配置如下:

<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    <init-param>
        <param-name>methodParam</param-name>
        <param-value>_method_</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

 在页面的form表单中设置method为Post,并添加一个如下的隐藏域:

  <input type="hidden" name="_method" value="put" />

查看HiddenHttpMethodFilter源码

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String paramValue = request.getParameter(methodParam);
        if("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) {
            String method = paramValue.toUpperCase(Locale.ENGLISH);
            HttpServletRequest wrapper = new HttpMethodRequestWrapper(request, method);
            filterChain.doFilter(wrapper, response);
        } else
        {
            filterChain.doFilter(request, response);
        }
}

     由源码可以看出,filter只对Post方法进行过滤,且需要添加参数名为_method的隐藏域,也可以设置其他参数名,比如想设置为_method_,可以在HiddenHttpMethodFilter配置类中设置初始化参数: 

<filter>
     <filter-name>HiddenHttpMethodFilter</filter-name>
     <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
     <init-param>
        <param-name>methodParam</param-name>
        <param-value>_method_</param-value>
     </init-param>
</filter> 

 HttpPutFormContentFilter

由HiddenHttpMethodFilter可知,html中的form的method值只能为post或get,我们可以通过HiddenHttpMethodFilter获取put表单中的参数键值对,而在Spring3中获取put表单的参数键值对还有另一种方法,即使用HttpPutFormContentFilter过滤器。

HttpPutFormContentFilter过滤器的作为就是获取put表单的值,并将之传递到Controller中标注了method为RequestMethod.put的方法中。

与HiddenHttpMethodFilter不同,在form中不用添加参数名为_method的隐藏域,且method不必是post,直接写成put,但该过滤器只能接受enctype值为application/x-www-form-urlencoded的表单,也就是说,在使用该过滤器时,form表单的代码必须如下:

<form action="" method="put" enctype="application/x-www-form-urlencoded">  

......  

</form>  

配置如下:

 

<filter>
   <filter-name>httpPutFormcontentFilter</filter-name>
   <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>httpPutFormContentFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

 ShallowEtagHeaderFilter

ShallowEtagHeaderFilter是spring提供的支持ETag的一个过滤器,所谓ETag是指被请求变量的实体值,是一个可以与Web资源关联的记号,而Web资源可以是一个Web页,也可以是JSON或XML文档,服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端,以下是服务器端返回的格式:

ETag:"50b1c1d4f775c61:df3"  

客户端的查询更新格式是这样的:

If-None-Match : W / "50b1c1d4f775c61:df3"  

   如果ETag没改变,则返回状态304然后不返回,这也和Last-Modified一样。

   ShallowEtagHeaderFilter会将JSP等的内容缓存,生成MD5的key,然后在response中作为Etage的header返回给客户端。下次客户端对相同的资源(或者说相同的url)发出请求时,客户端会将之前生成的key作为If-None-Match的值发送到server端。 Filter会客户端传来的值和服务器上的做比较,如果相同,则返回304;否则,将发送新的内容到客户端。

查看ShallowEtagHeaderFilter的源码如下:

 

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException{
  ShallowEtagResponseWrapper responseWrapper = new ShallowEtagResponseWrapper(response, null);
  filterChain.doFilter(request, responseWrapper);
  // 由此可知,服务器仍会处理请求
  byte[] body = responseWrapper.toByteArray();
  int statusCode = responseWrapper.getStatusCode();
 
  if (isEligibleForEtag(request, responseWrapper, statusCode, body)) {
    String responseETag = generateETagHeaderValue(body);
    response.setHeader(HEADER_ETAG, responseETag);
 
    String requestETag = request.getHeader(HEADER_IF_NONE_MATCH);
    if (responseETag.equals(requestETag)) {
      if (this.logger.isTraceEnabled()) {
        this.logger.trace("ETag [" + responseETag + "] equal to If-None-Match, sending 304");
      }
      response.setStatus(304);
    }
    else {
      if (this.logger.isTraceEnabled()) {
        this.logger.trace("ETag [" + responseETag + "] not equal to If-None-Match [" + requestETag + "], sending normal response");
      }
      copyBodyToResponse(body, response);
    }
  }
  else {
    if (this.logger.isTraceEnabled()) {
      this.logger.trace("Response with status code [" + statusCode + "] not eligible for ETag");
    }
    copyBodyToResponse(body, response);
  }
}

由源码可知,ShallowEtagHeaderFilter只能根据结果判断是否重新向客户端发送数据,并不会不处理请求,因此节省带宽,而不能提高服务器性能。

配置ShallowEtagHeaderFilter的代码如下:

 

<filter>  
   <filter-name>shallowEtagHeaderFilter</filter-name>  
   <filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</fliter-class>  
</filter>  
<filter-mapping>  
   <filter-name>shallowEtagHeaderFilter</filter-name>  
   <servlet-name>spring</servlet-name>  
</filter-mapping>

 

RequestContextFilter

这是在Spring2.0时添加的类,通过LocaleContextHolder和RequestContextHolder把Http request对象基于LocalThread绑定到请求提供服务的线程上。现在一般使用DispatcherServlet这个中央分发器。现在RequestContextFilter过滤器主要用于第三方的Servlet,如JSF的FacesServlet。在Spring2.5之前都是使用该过滤器配置。配置如下:

 

<filter>  
    <filter-name>RequestContextFilter</filter-name>  
    <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>  
</filter>  
<filter-mapping>  
    <filter-name>RequestContextFilter</filter-name>  
    <servlet-name>Faces Servlet</servlet-name>  
</filter-mapping>

DelegatingFilterProxy

该类其实并不能说是一个过滤器,它的原型是FilterToBeanProxy,即将Filter作为spring的bean,由spring来管理。该类提供了在web.xml和application context之间的联系。

Proxy for a standard Servlet 2.3 Filter, delegating to a Spring-managed bean that implements the Filter interface. 

有以下几个参数可以设置:

(1) contextAttribute,使用委派Bean的范围,其值必须从org.springframework.context.ApplicationContext.WebApplicationContext中取得,默认值是session;其他可选的有request、globalSession和application

(2) targetFilterLifecycle,是否调用Filter的init和destroy方法,默认为false。

(3)targetBeanName,被代理的过滤器的bean的名字,该bean的类必须实现Filter接口。

在web.xml中配置如下:

<filter>
   <filter-name>testFilter</filter-name>
   <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
   <init-param>
      <param-name>targetBeanName</param-name>
      <param-value>spring-bean-name</param-value>
   </init-param>
   <init-param>
      <param-name>contextAttribute</param-name>
     <param-value>session</param-value>
   </init-param>
   <init-param>
      <param-name>targetFilterLifecycle</param-name>
      <param-value>false</param-value>
   </init-param>
</filter>        
<filter-mapping>
   <filter-name>testFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

         testBean是被spring容器管理的对象,对象的类实现了Filter接口。或者可以不用配置这个参数,这样spring容器中所有实现了Filter接口的类都被代理,实际就是把Servlet容器中的filters同spring容器中的bean关联起来,方便spring进行管理。

如果不配置DelegatingFilterProxy,则由于filter比bean先加载,也就是spring会先加载filter指定的类到container中,这样filter中注入的spring bean就为null了。如果将filter中加入DelegatingFilterProxy类,"targetFilterLifecycle"指明作用于filter的所有生命周期。原理是,DelegatingFilterProxy类是一个代理类,所有的请求都会首先发到这个filter代理,然后再按照"filter-name"委派到spring中的这个bean。

此外,spring bean实现了Filter接口,但默认情况下,是由spring容器来管理其生命周期的(不是由tomcat这种服务器容器来管理)。如果设置"targetFilterLifecycle"为True,则spring来管理Filter.init()和Filter.destroy();若为false,则这两个方法失效。

在Spring Security中就是使用该类进行设置。即在web.xml中配置该过滤器,然后在spring security相关的配置中设置相应的过滤器bean。但是该类是spring-web包下的类,不属于Spring Security类。

 

  • 大小: 19.9 KB
  • 大小: 81.5 KB
分享到:
评论

相关推荐

    Spring MVC 入门实例

    这篇文章将教你快速地上手使用 Spring 框架. 如果你手上有一本《Spring in Action》, 那么你最好从第三部分"Spring 在 Web 层的应用--建立 Web 层"开始看, 否则那将是一场恶梦! 首先, 我需要在你心里建立起 Spring...

    spring security 参考手册中文版

    12.2.3使用RequestPostProcessor在Spring MVC测试中以用户身份运行 106 作为用户在Spring MVC测试中使用注释运行 108 12.2.4测试HTTP基本认证 109 12.3 SecurityMockMvcRequestBuilders 109 12.3.1测试基于表单的...

    使用Spring MVC拦截器实现日志记录的方法

    本篇文章主要介绍了使用Spring MVC拦截器实现日志记录的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    dynafilter-proj:Spring MVC中Json序列化的动态对象过滤

    @DynaFilter注释用于从任何数据类型中过滤掉感兴趣的字段,并与通常的请求处理程序方法结合使用: @RequestMapping ( value = " collection " , method = GET , produces = " application/json " )@DynaFilter ( ...

    jackson-dynamic-filter-spring-boot-starter:使用Jackson轻松动态确定过滤器的简便方法

    用于Spring Boot Starter,它提供了一种简便的方法,可以通过动态确定过滤,而无需直接在Java对象上编写注释,并且还可以与Spring MVC / Spring Boot很好地集成。 先决条件 Java 8及以上 3.0及更高版本 支持的...

    jackson-dynamic-filter:一种使用Jackson来动态确定过滤器的简便方法

    因此,此存储库提供了一种动态确定过滤器的简便方法,并且可以与Spring MVC / Spring Boot很好地集成。 对于Spring Boot: 要求Java 8 支持的Spring IO平台: 下载要使用Maven添加依赖项,请使用以下命令: ...

    springboot参考指南

    在Spring环境中使用YAML暴露属性 iii. 23.6.3. Multi-profile YAML文档 iv. 23.6.4. YAML缺点 vii. 23.7. 类型安全的配置属性 i. 23.7.1. 第三方配置 ii. 23.7.2. 松散的绑定(Relaxed binding) iii. 23.7.3. @...

    spring-boot-demo:Spring Boot和Spring Cloud和Spring Security演示案例(Spring学习示例实战项目)

    SpringBoot + SpringCloud + SpringSecurity学习过程中的二进制汇总,沉淀记录下学习历程 1.知识点图谱 所有博文集中发布在个人博客网站: 大致规划的内容包括以下章节,希望能用半年到一年(严重超期)的时间完成....

    SpringBoot一步配置Filter

    用Spring Initializr快速构建SpringBoot及整合MVC 关于Filter Filter:过滤器,属于Servlet规范中三个技术之一,本质是一种特殊Java类,可以拦截访问Web资源的请求与响应等操作,实现URL级别的权限访问控制、过滤...

    图书管理系统(框架)源码

    DTO为数据传输对象层,主要用来传输数据对象,MVC中Controller到View或者View到Controller的数据传输对象也放在这里面,不在使用ViewData。 Filter为拦截器层次,主要用来控制权限,操作日志的记录等。 Model为模型...

    Java_SpringMVC_Tutorial

    Spring MVC 就是类似于 Struts2 的 MVC 框架,属于 SpringFrameWork 的后续产品。 2 为什么学 Spring MVC? SpringMVC 与 Struts2 区别 对比项目 SrpingMVC Struts2 优势 国内市场情况 有大量用户,一般新项目启动...

    web页面模块化异步渲染struts-gpipe.zip

    struts-gpipe与struts和spring的整合:1,struts-gpipe提供注入spring容器bean的功能,用法一致。2,struts-gpipe提供ongl的功能,也就是会自动将模块属性引入 freemarker渲染,这一点是和spring mvc不同的,用过...

    电子商城系统设计实习报告.doc

    Java的W eb框架虽然各不相同,但基本也都是遵循特定的路数的:使用Servlet或者Filter拦截请 求,使用MVC的思想设计架构,使用约定,XML或 Annotation实现配置,运用Java面向对象的特点,面向抽象实现请求和响应的...

    Java Web程序设计教程

    4.1.3sql使用方法 65 4.2jdbc 67 4.2.1jdbc概述 67 4.2.2jdbc驱动程序 68 4.2.3使用jdbc读取数据 69 4.3项目实战——存储图书信息 73 本章小结 78 课后练习 79 第5章struts2框架基础 80 5.1mvc框架 80 ...

    webx3框架指南PDF教程附学习Demo

    • Spring MVC 以上框架都是非常优秀的。说实话,如果阿里巴巴网站在2001年开始,就有这么多可选择的话,无论选择哪一个都不会有问题。因为这些年来,所有的开源Web框架都在互相学习、并趋于相似。Webx也不例外,...

    拦截器和控制器的区别

    converter 转换器 i18n struts2 spring MVC 拦截器 interceptor 过滤器 filter web.xml implements filter filterchain arg2.doFilter(req,resp); 监听器 servlet application /session /request 6/8 个 ...

    training-advanced-java:高级 Java 课程的存储库

    培训高级 Java ... 如何更好地分离你的 spring/spring-mvc bean 声明,以及如何使用 Spring Boot 如何提供详尽的异常处理 如何使用 Java 8 CompletableFutures 实现多线程范式 如何使用 ServletFilter

    java面试题库2021.pdf

    ④JSTL、 DisplayTag 等常见标签库的用法 3、 Web 编程原理 ① HTTP 协议 ②请求/相应架构原理 ③web 容器 四、 JDBC 编程 1、 SQL 基础 2、 JDBC 基础 ①数据库 ②数据库连接池 ③事物管理, 批处理 3、 JDBC 进阶 ...

    J2EE应用开发详解

    57 4.3.7 Servlet协作 57 4.3.8 Filter 58 4.4 使用Servlet处理客户端请求 58 4.5 会话跟踪 61 4.5.1 使用Cookie进行会话跟踪 61 4.5.2 使用URL重写进行会话跟踪 62 4.5.3 使用隐藏表单域进行会话跟踪 63 4.6 小结 ...

Global site tag (gtag.js) - Google Analytics