- Filter 是什么,有什么用?
- Filter 是过滤器。
- Filter 可以在 Servlet 这个目标程序执行之前添加代码,也可以在目标 Servlet 执行之后添加代码。之前之后都可以添加过滤规则。
- 一般情况下,都是在过滤器当中编写公共代码。
7.Filter过滤器
- 当前的 OA 项目存在什么缺陷?
- DeptServlet、EmpServlet、OrderServlet,每一个 Servlet 都是处理自己相关的业务。在这些 Servlet 执行之前都是需要判断用户是否登录了,如果用户登录了,可以继续操作,如果没有登录,需要用户登录。这段判断用户是否登录的代码是固定的,并且在每一个 Servlet 类当中都需要编写,显然代码没有得到重复利用。包括每一个 Servlet 都要解决中文乱码问题,也有公共的代码。这些代码目前都是重复编写,并没有达到复用。怎么解决这个问题?
- 可以使用 Servlet 规范中的 Filter 过滤器来解决这个问题。
- DeptServlet、EmpServlet、OrderServlet,每一个 Servlet 都是处理自己相关的业务。在这些 Servlet 执行之前都是需要判断用户是否登录了,如果用户登录了,可以继续操作,如果没有登录,需要用户登录。这段判断用户是否登录的代码是固定的,并且在每一个 Servlet 类当中都需要编写,显然代码没有得到重复利用。包括每一个 Servlet 都要解决中文乱码问题,也有公共的代码。这些代码目前都是重复编写,并没有达到复用。怎么解决这个问题?
7.1 Filter过滤器概述
Filter 是什么,有什么用?
- Filter 是过滤器。
- Filter 可以在 Servlet 这个目标程序执行之前添加代码,也可以在目标 Servlet 执行之后添加代码。之前之后都可以添加过滤规则。
- 一般情况下,都是在过滤器当中编写公共代码。
一个过滤器怎么写呢?
第一步:编写一个 Java 类实现一个接口:
jarkata.servlet.Filter
。并且实现这个接口当中所有的方法。init
方法:在 Filter 对象第一次被创建之后调用,并且只调用一次。doFilter
方法:只要用户发送一次请求,则执行一次。发送 N 次请求,则执行 N 次。在这个方法中编写过滤规则。destroy
方法:在 Filter 对象被释放/销毁之前调用,并且只调用一次。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42package com.f.javaweb.filter;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author fzy
* @date 2023/12/23 13:28
*/
//@WebFilter({"/a.get", "/b.get"}) // 精确匹配
/*以下这个路径属于模糊匹配中的扩展匹配。以"*"开始, 注意这种路径不要以"/"开始*/
//@WebFilter("/dept/*") // 属于前缀匹配
//@WebFilter("/*") // 匹配所有路径
public class MyFilter implements Filter {
public MyFilter() { //可以不写
System.out.println("无参构造方法执行...");
}
public void init(FilterConfig filterConfig) throws ServletException { //在Filter接口中是default方法,可以不实现
System.out.println("init方法执行...");
}
public void destroy() { //在Filter接口中是default方法,可以不实现
System.out.println("destroy方法执行...");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 在请求的时候添加过滤规则
System.out.println("doFilter方法开始执行...");
// 执行下一个过滤器, 如果下一个不是过滤器了, 则执行目标程序Servlet
chain.doFilter(request, response);
// 在响应的时候添加过滤规则
System.out.println("doFilter方法执行结束...");
}
}第二步:在
web.xml
文件中对 Filter 进行配置,这个配置和 Servlet 很像。1
2
3
4
5
6
7
8<filter>
<filter-name>myfilter</filter-name>
<filter-class>com.f.javaweb.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myfilter</filter-name>
<url-pattern>*.get</url-pattern>
</filter-mapping>- 或者使用注解:
@WebFilter("*.get")
- 或者使用注解:
7.2 Filter过滤器执行原理
我们可以把
Servlet
程序看做是一个最终要执行的目标。我们可以使用过滤器Filter
来添加过滤代码,这个过滤代码可以添加到 Servlet 执行之前,也可以添加到 Servlet 执行之后。Filter 可以做到在 Servlet 这个目标程序执行之前过滤,也可以在目杨标程序执行之后过滤。- 与 Servlet 是和用户的请求路径对应的一样,过滤器也是和用户的请求路径对应的。

7.3 ★Filter注意事项
注意:
- Servlet 对象默认情况下,在服务器启动的时候是不会新建对象的。
- Filter 对象默认情况下,在服务器启动的时候就会新建对象。
- Servlet 是单例的,Filter 也是单例的。
- Filter 的生命周期:
- 和 Servlet 对象生命周期一致。
- 唯一的区别:Filter 默认情况下,在服务器启动阶段就实例化。Servlet 不会。
目标 Servlet 是否执行,取决于两个条件:
在过滤器当中是否编写了:
chain.doFilter(request, response);
代码。1
2
3
4
5
6
7
8
9
10
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// **在请求的时候添加过滤规则**
System.out.println("doFilter方法开始执行...");
// 执行下一个过滤器, 如果下一个不是过滤器了, 则执行目标程序Servlet
chain.doFilter(request, response);
// **在响应的时候添加过滤规则**
System.out.println("doFilter方法执行结束...");
}用户发送的请求路径是否和 Servlet 的请求路径一致。
chain.doFilter(request, response);
这行代码的作用:- 执行下一个过滤器,如果下面没有过滤器了,则执行目标程序 Servlet。
注意:在请求的时候和响应的时候都可以添加过滤规则。
注意:**
Filter
的优先级,天生就比Servlet
优先级高**。例如:/a.get
对应一个 Filter,也对应一个 Servlet。那么一定是先执行 Filter,然后再执行 Servlet。
关于 Filter 的配置路径:
- /a.do、/b.do、/dept/save。这些配置方式都是精确匹配。
- /* 匹配所有路径。
- *.do 后缀匹配。不要以 / 开始。
- /dept/* 前缀匹配。
关于多个 Filter 的执行顺序:
- 在
web.xml
文件中进行配置的时候,Filter 的执行顺序是什么?- 依靠
filter-mapping
标签的配置位置,越靠上优先级越高。 - 过滤器的配置一般写在 xml 文件中,便于控制过滤器的执行顺序。
- 依靠
- 使用
@WebFilter
的时候,Filter 的执行顺序是怎样的呢?- 执行顺序是:比较 Filter 这个类名。
- 比如:FilterA和FilterB,则先执行FilterA。
- 比如:Filter1和Filter2,则先执行Filter1。
- 执行顺序是:比较 Filter 这个类名。
过滤器的调用顺序,遵循栈数据结构。例如:
如果有两个过滤器 Filter1 和 Filter2,以及目标程序 Servlet,Filter1 的执行顺序在 Filter2 之前,且请求路径同时涉及到了这三个 Java 对象,且在 Filter1 和 Filter2 中有代码:
chain.doFilter(request, response);
,则执行顺序为:- 先执行 Filter1 在请求的时候添加的过滤规则。
- 再执行 Filter2 在请求的时候添加的过滤规则。
- 再执行 Servlet 的 service 方法。
- 再执行 Filter2 在响应的时候添加的过滤规则。
- 最后执行 Filter1 在响应的时候添加的过滤规则。

- 在
7.4 责任链设计模式
- Filter 过滤器这里有一个设计模式:责任链设计模式。
- 过滤器最大的优点:
- 在程序编译阶段不会确定调用顺序,因为 Filter 的调用顺序是配置到
web.xml
文件中的,只要修改web.xml
配置文件中filter-mapping
的顺序就可以调整Filter
的执行顺序。显然Filter
的执行顺序是在程序运行阶段动态组合的。那么这种设计模式被称为责任链设计模式。
- 在程序编译阶段不会确定调用顺序,因为 Filter 的调用顺序是配置到
- 责任链设计模式最大的核心思想:在程序运行阶段,动态地组合程序的调用顺序。
- 过滤器的配置一般写在 xml 文件中,便于控制过滤器的执行顺序。
- 过滤器最大的优点: