Filter过滤器学习笔记

一、Filter概述

1.1 什么是Filter

Filter(过滤器)是JavaWeb三大组件之一(Servlet、Filter、Listener),主要用于拦截请求并实现一些通用功能:

  • 拦截特性:所有对Web服务器资源的请求都必须先经过过滤器
  • 常见用途
    • ✅ 登录校验
    • ✅ 统一编码处理
    • ✅ 敏感字符过滤
    • ✅ 权限控制

1.2 工作原理图解

image.png

二、Filter快速入门

2.1 基础实现步骤

1. 定义过滤器类

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
@WebFilter(urlPatterns = "/*") // 拦截所有请求
public class DemoFilter implements Filter {

// 初始化方法(服务器启动时调用一次)
@Override
public void init(FilterConfig filterConfig) {
System.out.println("过滤器初始化...");
}

// 核心过滤方法(每次请求都会调用)
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("拦截到请求...");

// 关键放行操作!没有这行代码请求将被阻塞
chain.doFilter(request, response);
}

// 销毁方法(服务器关闭时调用一次)
@Override
public void destroy() {
System.out.println("过滤器销毁...");
}
}

2. 启用Servlet组件扫描

1
2
3
4
5
6
7
@ServletComponentScan // 必须添加!启用Servlet组件支持
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

2.2 注意事项

⚠️ 必须调用chain.doFilter():否则请求会被拦截,无法继续后续处理
⚠️ @ServletComponentScan注解:忘记添加会导致过滤器不生效

三、登录校验过滤器实战

3.1 设计思路

image.png

3.2 完整实现代码

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
@Slf4j
@WebFilter(urlPatterns = "/*")
public class TokenFilter implements Filter {

@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;

// 1. 获取请求URL
String url = request.getRequestURL().toString();
log.info("请求URL: {}", url);

// 2. 登录请求直接放行
if(url.contains("login")) {
chain.doFilter(request, response);
return;
}

// 3. 获取Token
String jwt = request.getHeader("token");

// 4. Token为空处理
if(!StringUtils.hasLength(jwt)) {
response.setStatus(HttpStatus.SC_UNAUTHORIZED);
response.getWriter().write("未携带令牌!");
return;
}

// 5. 验证Token有效性
try {
JwtUtils.parseJWT(jwt); // 解析验证
} catch (Exception e) {
response.setStatus(HttpStatus.SC_UNAUTHORIZED);
response.getWriter().write("无效令牌!");
return;
}

// 6. 验证通过,放行
chain.doFilter(request, response);
}
}

3.3 测试场景

测试场景 预期结果
未登录访问受限资源 自动跳转登录页
登录后访问资源 正常响应
Token过期访问 返回401错误

四、Filter高级特性

4.1 完整执行流程

1
2
3
4
5
6
7
8
9
10
public void doFilter(...) {
// 1. 前置处理逻辑
System.out.println("前置处理...");

// 2. 关键放行操作
chain.doFilter(request, response);

// 3. 后置处理逻辑
System.out.println("后置处理...");
}

执行顺序:
前置处理 -> 资源访问 -> 后置处理

4.2 拦截路径配置

配置方式 示例 说明
全部拦截 /* 拦截所有请求
路径拦截 /user/* 拦截/user下的所有请求
后缀拦截 *.jsp 拦截所有jsp页面
精确拦截 /login 只拦截/login请求

4.3 过滤器链

当存在多个过滤器时:

  1. 执行顺序:按照类名自然排序(如AbcFilter先于DemoFilter)
  2. 执行流程
    image.png

五、最佳实践建议

  1. 性能优化

    • init()方法中初始化耗时资源
    • 避免在doFilter()中进行复杂计算
  2. 异常处理

    1
    2
    3
    4
    5
    6
    try {
    chain.doFilter(request, response);
    } catch (Exception e) {
    // 统一异常处理
    response.sendError(500, "服务器错误");
    }
  3. 实用技巧

    • 使用@Order注解控制过滤器顺序(Spring环境下)
    • 通过FilterConfig获取初始化参数
  4. 常见问题

    • ❌ 忘记调用chain.doFilter()
    • ❌ 未添加@ServletComponentScan
    • ❌ 在过滤器中抛出未处理异常

通过本学习笔记,可以全面掌握Filter的核心概念和实际应用,特别是在登录校验等安全场景下的关键作用。建议结合实际项目进行练习,加深理解。