springboot拦截器配置的核心就三步:实现HandlerInterceptor接口、在配置类中注册并指定拦截路径、按需放行静态资源和登录接口。 下面从实际登录校验场景拆开讲,包含springboot拦截器不生效排查和与过滤器的区别。
springboot拦截器怎么配置:从登录校验场景落地
很多项目会在用户访问后台接口前校验登录态,比如检查session或token,用拦截器处理这类需求,比在每个Controller方法里写重复代码舒服得多。
第一步:实现HandlerInterceptor接口
新建一个类,实现HandlerInterceptor接口,通常重写preHandle方法就好,它会在请求到达Controller之前执行。
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object user = request.getSession().getAttribute("loginUser");
if (user == null) {
response.setStatus(401);
response.getWriter().write("未登录");
return false;
}
return true;
}
}
代码里没有魔术。preHandle返回true就放行,返回false直接中断请求,这里用session判断,实际项目换成token校验也一样。
第二步:注册拦截器并配置路径
新建配置类实现WebMvcConfigurer,重写addInterceptors方法。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/api/")
.excludePathPatterns("/api/login", "/api/register");
}
}
addPathPatterns指定要拦哪些路径,

excludePathPatterns指定放行哪些路径,这个顺序不能反:先指定拦截范围,再从里面排除白名单,如果登录接口本身也被拦了,那用户永远进不来。
第三步:放行静态资源和公开接口
springboot拦截器放行静态资源这个需求很常见,不配置的话,首页的css、js、图片全被拦截器挡下来,页面直接白屏,可以在excludePathPatterns里加上:
.excludePathPatterns("/static/", "/css/", "/js/", "/images/", "/login", "/error")
如果你用了Swagger或Knife4j,接口文档路径也要放行,比如/swagger-ui/、/v3/api-docs/,这部分是新手最容易漏掉的地方。
springboot拦截器和过滤器的区别:选型前先分清职责
很多开发者分不清springboot拦截器和过滤器的区别,结果要么用过滤器写了业务逻辑,要么用拦截器处理了编码问题,两者执行时机完全不同。
| 对比项 | 拦截器 | 过滤器 |
|---|---|---|
| 所属规范 | Spring框架提供 | Servlet规范提供 |
| 执行时机 | 在DispatcherServlet之后、Controller之前 | 在Servlet之前 |
| 能拿到Handler方法信息 | 能 | 不能 |
| 能注入Spring Bean | 能,交给Spring管理 | 默认不能直接注入 |
| 作用范围 | 只拦Spring MVC请求 | 所有进入容器的请求 |
| 适合场景 | 登录校验、权限判断、日志统计 | 字符编码、敏感词过滤、跨域处理 |
行业共识认为,拦截器更适合与业务绑定的逻辑,因为它能拿到具体要执行的Controller方法;过滤器适合底层通用的横切处理,比如统一编码、请求参数清洗,实际项目里两者经常配合使用,不存在谁替代谁。

springboot拦截器不生效:先查注册顺序和路径匹配
写完拦截器一跑,发现没拦住任何请求,或者把不该拦的也拦了,这类springboot拦截器不生效问题,多数情况下出在三个地方。
注册类没被Spring扫描
配置类上忘了加@Configuration注解,或者类放在没有被@SpringBootApplication扫描到的包外面,确认一下配置类在启动类同级或子级包下,并且有@Configuration。
路径匹配规则写错
addPathPatterns("/api/")只能拦到/api/abc,拦不到/api/abc/def这种多级路径,要拦多级,用/api/。excludePathPatterns里的路径写成了相对路径,比如"login",实际请求是/login,根本匹配不上。- 拦截路径写了但没放行静态资源,导致前端资源全挂。
多个拦截器执行顺序问题
注册多个拦截器时,顺序就是addInterceptor的调用顺序,先注册的先执行,如果把权限拦截器注册在登录拦截器前面,用户还没登录就被当成无权限处理,就会看到奇怪的结果,springboot拦截器注册顺序直接决定了preHandle的执行先后,多个拦截器都返回true时按照注册顺序链式执行,前面的返回false,后面的不会再执行。
实际工程里的两个高级配置
多个拦截器分工
建议按职责拆开:登录拦截器只管登录态,权限拦截器只查角色或权限点,这样每个拦截器逻辑简单,排错也容易。
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/api/").order(1);
registry.addInterceptor(new PermissionInterceptor()).addPathPatterns("/api/").order(2);
部分Spring版本支持order方法显式指定顺序,不支持的按照注册先后即可。
拦截器里获取Spring Bean

拦截器类如果直接new出来,用@Autowired注入的Service会是null,因为Spring容器不会管理手动new的对象,解决办法是在配置类里把拦截器声明为Bean,再用注入方式注册。
@Configuration
public class WebConfig implements WebMvcConfigurer {
private final LoginInterceptor loginInterceptor;
public WebConfig(LoginInterceptor loginInterceptor) {
this.loginInterceptor = loginInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/api/")
.excludePathPatterns("/api/login");
}
}
同时给LoginInterceptor加上@Component注解,让它成为Spring Bean,这个坑在实际项目中相当常见,尤其是从网上复制代码直接跑的时候。
springboot配置拦截器常见问题
springboot登录拦截器配置后为什么登录接口也被拦截?
因为没在excludePathPatterns中放行登录接口,或者放行路径写成了"login"而实际请求是"/login",正确写法是.excludePathPatterns("/api/login"),路径以项目实际映射为准。
springboot拦截器不生效可能有哪些原因?
配置类没加@Configuration、拦截路径与实际请求路径不匹配、多个拦截器中前一个返回false导致后续不执行、拦截器对象没有被Spring管理导致内部Bean注入失败,按上面三个模块逐一排查即可。
springboot拦截器和过滤器的区别到底怎么选?
过滤器处理Servlet层的通用逻辑,比如编码、日志、跨域;拦截器处理Spring MVC层的业务逻辑,比如登录态校验、权限控制,过滤器作用范围更靠前,拦截器能拿到Handler信息,两者选型依据是任务本身更靠近哪一层。
