过滤器Filter基础介绍
简单介绍
Filter过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。
过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等。
快速使用
定义Filter:定义一个类,实现 Filter 接口,并实现其所有方法。
配置Filter:Filter类上加@WebFilter注解,配置拦截路径。引导类上加 @ServletComponentScan 开启Servlet组件支持。
下方以登录令牌校验为例:
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
42
43
44
45
46
47
48
|
package com.yuanyu.filter;
import com.yuanyu.utils.JwtUtils;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
@Slf4j
@WebFilter(urlPatterns = "/*") // 所有请求都会被拦截
public class TokenFilter implements Filter { // 实现Filter(选的是servlet的)
// doFilter必须重写
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 获取到请求路径
String requestURI = request.getRequestURI(); // /login
// 判断路径是否为登录请求,路径中如果包含/login则放行
if (requestURI.contains("/login")) {
log.info("登录请求,放行");
filterChain.doFilter(request, response);
return;
}
// 获取请求头中的token
String token = request.getHeader("token");
// 判断token是否为空,如果为空则说明用户没有登录,返回错误信息(响应401状态码)
if (token == null || token.isEmpty()) {
log.info("令牌为空,响应401状态码");
response.setStatus(401);
return;
}
// 如果token存在,校验令牌,如果校验失败,返回错误信息(响应401状态码)
try {
JwtUtils.parseToken(token);
} catch (Exception e) {
log.info("令牌非法,响应401状态码");
response.setStatus(401);
return;
}
// 校验通过则放行
log.info("令牌校验通过,放行");
filterChain.doFilter(request, response);
}
}
|
别忘了在启动类上加@ServletComponentScan
1
2
3
4
5
6
7
|
@ServletComponentScan // 不加这个,Filter就无法使用
@SpringBootApplication
public class TliasWebManagementApplication {
public static void main(String[] args) {
SpringApplication.run(TliasWebManagementApplication.class, args);
}
}
|
效果:
不带令牌时:
携带正确令牌时:
执行过程
其实放行后,资源访问完还会回到Filter中
1
2
3
4
5
6
7
8
9
10
11
|
@Slf4j
@WebFilter(urlPatterns = "/*")
public class DemoFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("放行前……");
log.info("放行……");
filterChain.doFilter(servletRequest,servletResponse);
log.info("放行后……");
}
}
|

过滤器链
一个web应用中,可以配置多个过滤器,这多个过滤器就形成了一个过滤器链。
注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序。
如有两个过滤器,一个叫AppleFilter,另一个叫BananaFilter,AppleFilter就会先拦截,放行后再到BananaFilter

如果项目中还有拦截器(Interceptor),也是先经过过滤器再进入拦截器
Filter与Interceptor的区别
接口规范不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerInterceptor接口。
拦截范围不同:过滤器Filter会拦截所有的资源,而Interceptor只会拦截Spring环境中的资源。