Spring Boot Mock MVC环境下AdminFilter过滤器匹配错误URL模式问题排查
问题原因
核心原因是你在AdminFilter类上添加了@Component注解:
- Spring Boot的Filter自动配置规则会自动将所有实现了
Filter接口、且被Spring容器托管的Bean注册为全局过滤器,默认匹配所有路径(/*),这个自动注册的过滤器实例会对所有请求生效。 - 你自己通过
FilterRegistrationBean注册的是手动new出来的AdminFilter实例,仅对指定的两个路径生效,此时你的Spring环境中实际存在两个AdminFilter实例在运行。
至于为什么Postman访问时你没感知到异常:你的AdminFilter代码依赖request.getAttribute("userId"),Postman访问其他接口时如果没有携带有效JWT Token,前置的JWT解析过滤器不会给request设置userId属性,代码在UUID.fromString步骤就会抛出空指针,你可能被全局异常处理的返回掩盖了过滤器实际已经被触发的事实,而单元测试中你携带了有效Token,所以成功触发了后续的管理员校验逻辑,暴露了问题。
解决方案
直接删除AdminFilter类上的@Component注解即可:
删除后Spring不会再自动注册全局的AdminFilter实例,只有你通过FilterRegistrationBean手动配置的实例会生效,仅拦截你指定的/api/user/activate和/api/user/deactivate路径。
如果你确实需要保留@Component注解,也可以修改FilterRegistrationBean配置,覆盖默认的全局注册规则,将容器中托管的AdminFilter实例绑定到指定路径:
@Bean public FilterRegistrationBean<AdminFilter> adminFilterRegistrationBean(AdminFilter adminFilter) { FilterRegistrationBean<AdminFilter> registrationBean = new FilterRegistrationBean<>(); // 直接注入容器中的AdminFilter实例,而非手动new registrationBean.setFilter(adminFilter); registrationBean.addUrlPatterns("/api/user/activate"); registrationBean.addUrlPatterns("/api/user/deactivate"); registrationBean.setOrder(Integer.MAX_VALUE); registrationBean.setName("adminFilter"); return registrationBean; }
这种方式不如直接删除@Component简洁,更推荐第一种方案。
内容的提问来源于stack exchange,提问作者alcatraz
相关产品推荐
相关产品推荐

