Filter过滤器

Filter过滤器

所谓Filter

当一个请求在到达服务器软件之后,服务器软件响应请求时会找到相关的资源,如一个Html页面,一个JSP页面,一个servlet,Filter所做的事情,就是拦截这些请求,然后对它进行预处理。

image-20211230000319755

要注意,Filter不仅仅能够截拦Servlet,对于任意的URL(这个URL可以指向一个html,也可以指向一个jsp),如:http://www.argentoaskia.tech/resource.html,也是可以拦截的。

配置编写Filter

编写Filter的步骤应如下:

  1. 新建Filter的Java类
  2. 让该类实现Filter接口
  3. 在doFilter()方法中进行求情拦截
  4. 给该类添加@WebFilter注解,并指定要拦截的URL,或者在Web.xml中添加Filter配置,如:
1
2
3
4
5
6
7
8
9
10
11
<filter>
<filter-name>filter</filter-name>
<filter-class>FittlerDemo1.ABCFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<!--
<servlet-name>demo1</servlet-name>
-->
<urlPattern>/result</urlPattern>
</filter-mapping>

完整的Filter可以参考:

image-20211230000952257

过滤器执行流程

对于一个过滤器他的执行流程是双向的,也就是说它实际上遵循下面的流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
graph LR
A[客户端请求] -->|被截拦| B[过滤器1]
B[过滤器1] -->|过滤器1执行filterChain.doFilter方法之前的代码| D(filterChain)
D(filterChain) -->|过滤器1调用filterChain.doFilter方法到| C[过滤器2]
C[过滤器2] -->|过滤器2执行filterChain.doFilter方法之前的代码| D(filterChain)
D(filterChain) -->|过滤器2调用filterChain.doFilter方法到| E[过滤器3]
E[过滤器3] -->|过滤器3执行filterChain.doFilter方法之前的代码| D(filterChain)
D(filterChain) -->|过滤器3调用filterChain.doFilter方法到| F[过滤器4]
F[过滤器4] -->|过滤器4执行filterChain.doFilter方法之前的代码| D(filterChain)
D(filterChain) -->|没有其他过滤器 将会调用请求资源| G[Servlet或者JSP或者HTML]
G[Servlet或者JSP或者HTML] -->|执行完成 回到过滤器4|H[过滤器4]
H[过滤器4] -->|执行filterChain.doFilter方法之后的代码| I[过滤器3]
I[过滤器3] -->|执行filterChain.doFilter方法之后的代码| J[过滤器2]
J[过滤器2] -->|执行filterChain.doFilter方法之后的代码| K[过滤器1]

过滤器生命周期

Filter的生命周期主要有三个:

  • init()
  • doFilter()
  • destroy()

过滤器配置

@WebFilter源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebFilter {
String description() default ""; // 该filter的描述
String displayName() default ""; // 过滤器的显示名称
WebInitParam[] initParams() default {}; // 初始化参数
String filterName() default ""; // 过滤器名称
String smallIcon() default ""; // The small-icon of the filter
String largeIcon() default ""; // The large-icon of the filter
String[] servletNames() default {}; // The names of the servlets to which the filter applies.
String[] value() default {}; // The URL patterns to which the filter applies
String[] urlPatterns() default {}; // The URL patterns to which the filter applies
// The dispatcher types to which the filter applies
DispatcherType[] dispatcherTypes() default {DispatcherType.REQUEST};
// Declares whether the filter supports asynchronous operation mode.
boolean asyncSupported() default false;

}

image-20211230010247571

配置方式拦截

配置方式拦截主要涉及到DispatcherType的指定,有五种方式:

  • FORWARD、INCLUDE用于当使用RequestDispatcher的forward()、include()时应用该Filter
  • ERROR用于当请求的URL会404时,应用该Filter
  • REQUEST默认选项,当发送请求的时候应用该Filter
  • ASYNC异步拦截,用于Ajax

配置路径拦截

  1. 具体资源路径:/index.jsp
  2. 拦截目录:/user/*:拦截某个目录下的资源
  3. 后缀名拦截:*.jsp:拦截所有的jsp文件
  4. 拦截所有资源:/*

多个Filter作用顺序(过滤器链)

一个Servlet中配置多个Filter的执行顺序是一件很有意思的事情,如果一个项目配置了多个Filter,这些Filter里面包括使用urlPatterns来指定拦截的,使用servletNames来指定拦截Servlet的,有在Web.xml中定义的,也有使用@WebFilter定义的。

无论有多少,首先都会执行配置了urlPatterns属性的Filters,在这些配置了urlPatterns属性的Filters里面,又优先执行Web.xml中定义的Filters,根据Web.xml中的Filters的上下文排列顺序来执行然后才执行使用@WebFilter的Filter,执行@WebFilter的Filter,根据类名来判断执行顺序,不区分大小写。

然后才会执行配置了servlet-name属性的Filters,执行顺序同配置了urlPatterns属性的Filters一样。