统一拦截校验的目的:把“是否登录/Token 是否合法”的重复代码,从每个 Controller 里拿出来,集中在一个地方做。实现方式常见两种:Filter(过滤器) 和 Interceptor(拦截器) 。
1)Filter vs Interceptor:一句话区别
- Filter:JavaWeb 标准组件,在进入 Spring 之前就能拦截(更“底层”),能拦截所有资源(静态资源/Servlet/Controller 都能拦)。
- Interceptor:Spring 提供的机制,只拦截 Spring MVC 的 Controller 调用(更“贴近业务”)。
2)统一拦截校验要做的事(两者逻辑一样)
核心流程(和你讲义一致):
- 拿到请求 URL
- 如果是
/login(或放行名单),直接放行 - 从请求头拿 token(如
token) - token 为空 → 401
- 解析 JWT 失败(过期/篡改/密钥不对)→ 401
- 解析成功 → 放行
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