Spring框架无需Spring Security,如何在Servlet过滤器中指定HTTP方法?
非Spring Security环境下为过滤器指定HTTP请求方法的优雅方案
问题背景
在Spring Security中,我们可以通过antMatcher轻松为过滤器的URL映射指定GET/POST/PUT等HTTP方法,仅让特定方法的请求触发过滤器逻辑。但脱离Spring Security环境时,如何实现同样的效果?是否只能在OncePerRequestFilter的doFilterInternal方法里通过繁琐的switch判断请求方法?
比如之前的判断代码:
switch(request.getMethod()) { ... }
以及现有的FilterRegistrationBean配置:
@Bean public FilterRegistrationBean<CustomFilter> registrationBean(){ FilterRegistrationBean<CustomFilter> registration = new FilterRegistrationBean<>(); registration.setFilter(customFilter); registration.addUrlPatterns("/open/*"); /*may be it is possible to addHttpMethods?*/ registration.setName("customLoggingFilter"); registration.setOrder(2); return registration; }
优雅解决方案
方案一:自定义RequestMatcher分离匹配逻辑
Spring的FilterRegistrationBean本身没有直接提供HTTP方法配置API,但可以通过自定义RequestMatcher实现URL与HTTP方法的联合匹配,避免在过滤器内部写硬编码判断。
- 实现自定义匹配器
public class MethodAndUrlMatcher implements RequestMatcher { private final AntPathMatcher pathMatcher = new AntPathMatcher(); private final Set<String> allowedMethods; private final String urlPattern; public MethodAndUrlMatcher(String urlPattern, String... allowedMethods) { this.urlPattern = urlPattern; this.allowedMethods = Set.of(allowedMethods); } @Override public boolean matches(HttpServletRequest request) { boolean urlMatches = pathMatcher.match(urlPattern, request.getServletPath()); boolean methodMatches = allowedMethods.contains(request.getMethod()); return urlMatches && methodMatches; } }
- 在自定义过滤器中注入匹配器
@Component public class CustomFilter extends OncePerRequestFilter { private final MethodAndUrlMatcher matcher; // 初始化时指定要匹配的URL和允许的HTTP方法 public CustomFilter() { this.matcher = new MethodAndUrlMatcher("/open/*", "GET", "POST"); } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (matcher.matches(request)) { // 执行你的过滤器核心逻辑 // 示例:记录请求信息 System.out.println("处理请求:" + request.getMethod() + " " + request.getServletPath()); } filterChain.doFilter(request, response); } }
- 保持原有
FilterRegistrationBean配置不变即可,匹配逻辑已交由MethodAndUrlMatcher处理。
方案二:扩展FilterRegistrationBean实现方法配置
如果希望直接在注册Bean的层面配置HTTP方法,可以扩展FilterRegistrationBean,添加方法匹配逻辑:
- 扩展FilterRegistrationBean
public class MethodFilterRegistrationBean<T extends Filter> extends FilterRegistrationBean<T> { private Set<String> allowedMethods; private final AntPathMatcher pathMatcher = new AntPathMatcher(); public void setAllowedMethods(String... methods) { this.allowedMethods = Set.of(methods); } @Override public boolean matches(HttpServletRequest request) { // 先判断URL是否匹配 boolean urlMatches = super.matches(request); if (!urlMatches) { return false; } // 再判断HTTP方法是否在允许列表中 return allowedMethods == null || allowedMethods.contains(request.getMethod()); } }
- 使用扩展类配置过滤器
@Bean public MethodFilterRegistrationBean<CustomFilter> registrationBean(CustomFilter customFilter){ MethodFilterRegistrationBean<CustomFilter> registration = new MethodFilterRegistrationBean<>(); registration.setFilter(customFilter); registration.addUrlPatterns("/open/*"); // 直接指定允许的HTTP方法 registration.setAllowedMethods("GET", "POST"); registration.setName("customLoggingFilter"); registration.setOrder(2); return registration; }
这种方式下,过滤器只会处理符合URL规则且HTTP方法在允许列表中的请求,无需在过滤器内部添加判断逻辑。
补充说明
原生Servlet的FilterRegistration接口本身并没有提供指定HTTP方法的配置项,因此必须通过自定义匹配逻辑实现上述效果。相比在过滤器内部写switch判断,上面两种方案更符合单一职责原则,也更便于后续维护和扩展。
内容的提问来源于stack exchange,提问作者Bogdan Zaranik
相关产品推荐
相关产品推荐

