欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringMVC 过滤器Filter使用解析

程序员文章站 2022-03-10 14:15:19
...
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>day17-20180402</display-name>
  
  <!-- 1.配置一个ServletContext监听器 -->
 <!--  <listener>
      <listener-class>com.gyf.web.listener.MyServletContextListener</listener-class>
  </listener> -->
  
  <!-- 2.配置一个Session监听器 -->
 <!--  <listener>
      <listener-class>com.gyf.web.listener.MyHttpSessionListener</listener-class>
  </listener> -->
  
  <!-- 3.配置一个Request监听器 -->
  <!-- <listener>
      <listener-class>com.gyf.web.listener.MyHttpRequestListener</listener-class>
  </listener> -->
  
  <!-- 4.配置一个ServletContext属性监听器 -->
 <!--  <listener>
      <listener-class>com.gyf.web.listener.MyServletContextAttributeListener</listener-class>
  </listener> -->

    <!-- 5.配置一个过滤器,用于拦截请求 -->
    <filter>
        <filter-name>myfilter</filter-name>
        <filter-class>com.gyf.web.filter.MyFilter</filter-class>
        <!-- 初始化参数 -->
        <init-param>
            <param-name>username</param-name>
            <param-value>zhagsan</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>123456abcdefg</param-value>
        </init-param>
    </filter>

    <!-- 过滤器的拦截规则 -->
    <filter-mapping>
        <filter-name>myfilter</filter-name>
        <!-- 拦截任何一个请求 -->
        <!-- <url-pattern>/*</url-pattern> -->
        
        <!-- 只拦截jsp请求 不能写成【/*.jsp】,否则就会报错  -->
        <!-- <url-pattern>/*.jsp</url-pattern> -->
        
        <!-- 只想拦截某一个Servlet -->
        <url-pattern>/PersonListServlet</url-pattern>
        
        <!--  配置拦截的方式-->
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
  
  <!-- 6.多个过滤器 -->
  <!-- <filter>
      <filter-name>myfilter1</filter-name>
      <filter-class>com.gyf.web.filter.MyFilter1</filter-class>
  </filter>
  <filter>
      <filter-name>myfilter2</filter-name>
      <filter-class>com.gyf.web.filter.MyFilter2</filter-class>
  </filter>

    <filter-mapping>
        <filter-name>myfilter1</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>myfilter2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping> -->

   
  
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

SpringMVC 过滤器Filter使用解析

SpringMVC框架是一个成熟的优秀java web开发框架,学习研究框架设计有助于我们更好的理解和掌握spring MVC,设计和写出更符合的结构和代码。

本节主要是研读SpringMVC框架中的过滤器设置,以编码处理过滤器为例来学习框架内是怎样设置过滤器的。

如上所示的spring-web.jar包结构所示, Spring的web包中中提供有很多过滤器,这些过滤器位于org.springframework.web.filter并且理所当然地实现了javax.servlet.Filter,

不过实现的方式有以下几类:

    (1) 直接实现Filter,这一类过滤器只有CompositeFilter;

    (2) 继承抽象类GenericFilterBean,该类实现了javax.servlet.Filter,这一类的过滤器只有一个,即DelegatingFilterProxy;

    (3) 继承抽象类OncePerRequestFilter,该类为GenericFilterBean的直接子类,这一类过滤器包括CharacterEncodingFilter、HiddenHttpMethodFilter、HttpPutFormContentFilter、RequestContextFilter和ShallowEtagHeaderFilter;

    (4) 继承抽象类AbstractRequestLoggingFilter,该类为OncePerRequestFilter的直接子类,这一类过滤器包括CommonsRequestLoggingFilter、Log4jNestedDiagnosticContextFilter和ServletContextRequestLoggingFilter。

过滤器放在容器结构的什么位置?

过滤器放在web资源之前,可以在请求抵达它所应用的web资源(可以是一个Servlet、一个Jsp页面,甚至是一个HTML页面)之前截获进入的请求,并且在它返回到客户之前截获输出请求。Filter:用来拦截请求,处于客户端与被请求资源之间,目的是重用代码。Filter链,在web.xml中哪个先配置,哪个就先调用。在filter中也可以配置一些初始化参数。

Java中的Filter 并不是一个标准的Servlet ,它不能处理用户请求,也不能对客户端生成响应。 主要用于对HttpServletRequest 进行预处理,也可以对HttpServletResponse 进行后处理,是个典型的处理链。

Filter 有如下几个种类:

l 用户授权的Filter: Filter 负责检查用户请求,根据请求过滤用户非法请求。

l 日志Filter: 详细记录某些特殊的用户请求。

l 负责解码的Filter: 包括对非标准编码的请求解码。

l 能改变XML 内容的XSLTFilter 等。

Filter 有如下几个用处:

l 在HttpServletRequest 到达Servlet 之前,拦截客户的HttpServletRequest 。

l 根据需要检查HttpServletRequest ,也可以修改HttpServletRequest 头和数据。

l 在HttpServletResponse 到达客户端之前,拦截HttpServletResponse 。

l 根据需要检查HttpServletResponse ,可以修改HttpServletResponse 头和数据。

创建一个Filter 只需两个步骤:
(1)创建Filter 处理类:

(2)在web.xml 文件中配置Filter 。

创建Filter 必须实现javax.servlet.Filter 接口,在该接口中定义了三个方法。
• void init(FilterConfig config): 用于完成Filter 的初始化。
• void destroy(): 用于Filter 销毁前,完成某些资源的回收。
• void doFilter(ServletRequest request, ServletResponse response,FilterChain chain): 实现过滤功能,该方法就是对每个请求及响应增加的额外处理。

过滤器Filter也具有生命周期:init()->doFilter()->destroy(),由部署文件中的filter元素驱动。

参照编码过滤器示例来查看怎么实现的

首先配置在web.xml文件里的规则如下

<!-- 编码处理过滤器 -->

   <filter>

      <filter-name>encodingFilter</filter-name>

      <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

      <init-param>

         <param-name>encoding</param-name>

         <param-value>utf-8</param-value>

      </init-param>

      <init-param>

         <param-name>forceEncoding</param-name>

         <param-value>true</param-value>

      </init-param>

    </filter>

    

    <filter-mapping>

       <filter-name>encodingFilter</filter-name>

       <url-pattern>*.do</url-pattern>

    </filter-mapping>

其中,filter-class 为过滤器Filter类,init-prama为注入的set参数

Filter-mapping中的url-pattern为过滤的url类型

类的继承关系

CharacterEncodingFilter r类继承了 OncePerRequestFilter 类

public class CharacterEncodingFilter extends OncePerRequestFilter

而OncePerRequestFilter 类又继承了GenericFilterBean 类

public abstract class OncePerRequestFilter extends GenericFilterBean

public abstract class GenericFilterBean implements

   Filter, BeanNameAware, EnvironmentAware, ServletContextAware, InitializingBean, DisposableBean

设置编码的核心代码为

@Override

   protected void doFilterInternal(

         HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)

         throws ServletException, IOException {

 

      if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {

         request.setCharacterEncoding(this.encoding);

         if (this.forceEncoding) {

            response.setCharacterEncoding(this.encoding);

         }

      }

      filterChain.doFilter(request, response);

   }

 

其中filterChain为过滤器链,表示执行完这个过滤器之后接着执行下一个过滤器

区别

     我们在使用过滤器时,通常没必要知道GenericFilterBean、OncePerRequestFilter和AbstractRequestLoggingFilter,但不防碍我们了解这几个类,就上文所述,AbstractRequestLoggingFilter继承自OncePerRequestFilter,OncePerRequestFilter继承自GenericFilterBean,所以我们知道,genericFilterBean是任何类型的过滤器的一个比较方便的超类,这个类主要实现的就是从web.xml文件中取得init-param中设定的值,然后对Filter进行初始化(当然,其子类可以覆盖init方法)。

     OncePerRequestFilter继承自GenericFilterBean,那么它自然知道怎么去获取配置文件中的属性及其值,所以其重点不在于取值,而在于确保在接收到一个request后,每个filter只执行一次,它的子类只需要关注Filter的具体实现即doFilterInternal。

    AbstractRequestLoggingFilter是对OncePerRequestFilter的扩展,它除了遗传了其父类及祖先类的所有功能外,还在doFilterInternal中决定了在过滤之前和之后执行的事件,它的子类关注的是beforeRequest和afterRequest。

   总体来说,这三个类分别执行了Filter的某部分功能,当然,具体如何执行由它们的子类规定,若你需要实现自己的过滤器,也可以根据上文所述继承你所需要的类。
相关标签: filter