初识统一拦截校验(Filter 和 Interceptor)

33 阅读2分钟

统一拦截校验的目的:把“是否登录/Token 是否合法”的重复代码,从每个 Controller 里拿出来,集中在一个地方做。实现方式常见两种:Filter(过滤器)Interceptor(拦截器)


1)Filter vs Interceptor:一句话区别

  • Filter:JavaWeb 标准组件,在进入 Spring 之前就能拦截(更“底层”),能拦截所有资源(静态资源/Servlet/Controller 都能拦)。
  • Interceptor:Spring 提供的机制,只拦截 Spring MVC 的 Controller 调用(更“贴近业务”)。

2)统一拦截校验要做的事(两者逻辑一样)

核心流程(和你讲义一致):

  1. 拿到请求 URL
  2. 如果是 /login(或放行名单),直接放行
  3. 从请求头拿 token(如 token
  4. token 为空 → 401
  5. 解析 JWT 失败(过期/篡改/密钥不对)→ 401
  6. 解析成功 → 放行

3)Filter(过滤器)怎么做统一校验

3.1 特点

  • 作用范围更广:/* 可拦截所有请求
  • 生命周期:init(启动一次)→ doFilter(每次请求)→ destroy(关闭一次)
  • 放行方式:chain.doFilter(request,response)

3.2 登录校验 Filter 示例

@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;

        String url = request.getRequestURL().toString();

        // 1) 放行登录
        if (url.contains("login")) {
            chain.doFilter(request, response);
            return;
        }

        // 2) 取 token
        String jwt = request.getHeader("token");
        if (jwt == null || jwt.isEmpty()) {
            response.setStatus(401);
            return;
        }

        // 3) 校验 token
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) {
            response.setStatus(401);
            return;
        }

        // 4) 放行
        chain.doFilter(request, response);
    }
}

⚠️ Filter 生效要点:

  • 类上 @WebFilter
  • 启动类加 @ServletComponentScan

4)Interceptor(拦截器)怎么做统一校验

4.1 特点

  • 只拦截 Controller 方法(Spring MVC 里的请求)

  • 典型三个阶段:

    • preHandle:方法执行前(最常用做登录校验)
    • postHandle:方法执行后、视图渲染前
    • afterCompletion:最后(清理资源/日志)
  • 放行方式:preHandle 返回 true/false

4.2 登录校验 Interceptor 示例

@Component
public class TokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        String url = request.getRequestURL().toString();

        // 1) 放行登录
        if (url.contains("login")) {
            return true;
        }

        // 2) 取 token
        String jwt = request.getHeader("token");
        if (jwt == null || jwt.isEmpty()) {
            response.setStatus(401);
            return false;
        }

        // 3) 校验 token
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) {
            response.setStatus(401);
            return false;
        }

        return true; // 放行
    }
}

注册拦截器:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired private TokenInterceptor tokenInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(tokenInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/login");
    }
}

✅ 实战建议:放行用 excludePathPatterns 更规范,别用 url.contains("login")(容易误判)。


5)执行顺序(面试常问)

一次请求进来大致顺序:
Filter(放行前) → DispatcherServlet → Interceptor.preHandle → Controller → Interceptor.postHandle → Interceptor.afterCompletion → Filter(放行后)


6)到底选哪个?

常见推荐

  • 只做 Spring MVC 接口认证:优先 Interceptor(更贴近业务、配置灵活)
  • 需要拦截所有资源(包含静态资源/非 Spring 请求)或做更底层的通用处理:用 Filter