过滤器Filter基础介绍

简单介绍了Filter的使用以及与Interceptor的区别

过滤器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);
    }
}

效果:

不带令牌时:

image-20250920152430896

携带正确令牌时:

image-20250920152451901

执行过程

其实放行后,资源访问完还会回到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("放行后……");
    }
}

image-20250920190536368

过滤器链

一个web应用中,可以配置多个过滤器,这多个过滤器就形成了一个过滤器链。

注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序。

如有两个过滤器,一个叫AppleFilter,另一个叫BananaFilter,AppleFilter就会先拦截,放行后再到BananaFilter

image-20250920192937709

如果项目中还有拦截器(Interceptor),也是先经过过滤器再进入拦截器

Filter与Interceptor的区别

接口规范不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerInterceptor接口。

拦截范围不同:过滤器Filter会拦截所有的资源,而Interceptor只会拦截Spring环境中的资源。

本站于2025年3月26日建立
使用 Hugo 构建
主题 StackJimmy 设计