You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让实现ContainerRequestFilter和ContainerResponseFilter的过滤器匹配特定正则URL?

嗨,我来帮你搞定这个问题!在JAX-RS框架中,要让你的ContainerRequestFilter和ContainerResponseFilter只对符合特定正则表达式的URL生效,有两种实用方案,我给你拆解清楚:

方案一:过滤器内部直接做URL匹配(最简单直接)

这种方式不需要额外注解,直接在过滤器代码里判断请求URL是否符合正则,不符合就跳过过滤逻辑。

步骤示例:

  1. 编写过滤器类,预编译正则表达式(提升性能),然后在filter方法里做匹配判断:
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.ContainerResponseContext;
import java.io.IOException;
import java.util.regex.Pattern;

// 请求过滤器示例
public class TargetUrlRequestFilter implements ContainerRequestFilter {
    // 预编译目标URL正则,比如匹配 /api/v1/users/数字 这类路径
    private static final Pattern TARGET_URL_PATTERN = Pattern.compile("/api/v1/users/\\d+");

    @Override
    public void filter(ContainerRequestContext requestContext) {
        // 获取请求的相对路径(自动去掉应用的base URI,更准确)
        String requestPath = requestContext.getUriInfo().getPath();
        
        // 如果URL不匹配正则,直接返回,不执行后续过滤逻辑
        if (!TARGET_URL_PATTERN.matcher(requestPath).matches()) {
            return;
        }

        // 这里写你的请求过滤逻辑,比如校验Token、修改请求头等
        System.out.println("处理符合正则的请求:" + requestPath);
    }
}

// 响应过滤器示例(逻辑类似)
public class TargetUrlResponseFilter implements ContainerResponseFilter {
    private static final Pattern TARGET_URL_PATTERN = Pattern.compile("/api/v1/users/\\d+");

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        String requestPath = requestContext.getUriInfo().getPath();
        if (!TARGET_URL_PATTERN.matcher(requestPath).matches()) {
            return;
        }

        // 这里写你的响应过滤逻辑,比如添加响应头、修改响应体等
        responseContext.getHeaders().add("X-Filtered", "true");
    }
}
  1. 注册过滤器:
    • 给过滤器类添加@Provider注解,让JAX-RS自动扫描注册;
    • 或者在你的Application子类中手动注册:
      import javax.ws.rs.core.Application;
      import java.util.HashSet;
      import java.util.Set;
      
      public class MyApplication extends Application {
          @Override
          public Set<Class<?>> getClasses() {
              Set<Class<?>> classes = new HashSet<>();
              classes.add(TargetUrlRequestFilter.class);
              classes.add(TargetUrlResponseFilter.class);
              return classes;
          }
      }
      
方案二:使用自定义注解+动态绑定(灵活适配不同URL规则)

如果需要给不同的资源方法/类指定不同的正则规则,或者想通过注解来标记需要过滤的目标,这种方案更灵活。

步骤示例:

  1. 定义带正则参数的自定义绑定注解:
import javax.ws.rs.NameBinding;
import java.lang.annotation.*;

@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface FilterForRegex {
    // 用来指定目标URL的正则表达式
    String value();
}
  1. 编写动态绑定类,根据资源上的注解决定是否应用过滤器:
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.FeatureContext;
import java.util.regex.Pattern;

public class RegexFilterDynamicBinder implements DynamicFeature {
    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext context) {
        // 先检查资源方法有没有注解,没有再检查资源类
        FilterForRegex annotation = resourceInfo.getResourceMethod().getAnnotation(FilterForRegex.class);
        if (annotation == null) {
            annotation = resourceInfo.getResourceClass().getAnnotation(FilterForRegex.class);
        }

        if (annotation != null) {
            // 拿到注解里的正则,注册对应的过滤器实例
            String regex = annotation.value();
            context.register(new DynamicRequestFilter(regex));
            context.register(new DynamicResponseFilter(regex));
        }
    }
}
  1. 编写支持动态正则的过滤器:
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import java.io.IOException;
import java.util.regex.Pattern;

public class DynamicRequestFilter implements ContainerRequestFilter {
    private final Pattern targetPattern;

    // 构造函数传入正则表达式
    public DynamicRequestFilter(String regex) {
        this.targetPattern = Pattern.compile(regex);
    }

    @Override
    public void filter(ContainerRequestContext requestContext) {
        String requestPath = requestContext.getUriInfo().getPath();
        if (targetPattern.matcher(requestPath).matches()) {
            // 执行请求过滤逻辑
            System.out.println("处理正则[" + targetPattern.pattern() + "]的请求");
        }
    }
}

public class DynamicResponseFilter implements ContainerResponseFilter {
    private final Pattern targetPattern;

    public DynamicResponseFilter(String regex) {
        this.targetPattern = Pattern.compile(regex);
    }

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        String requestPath = requestContext.getUriInfo().getPath();
        if (targetPattern.matcher(requestPath).matches()) {
            // 执行响应过滤逻辑
            responseContext.getHeaders().add("X-Dynamic-Filter", "true");
        }
    }
}
  1. 在资源类/方法上标注注解:
@Path("/api/v1/users")
public class UserResource {

    // 只对这个方法的URL应用过滤器,正则匹配 /api/v1/users/数字
    @FilterForRegex("/api/v1/users/\\d+")
    @GET
    @Path("/{id}")
    public Response getUser(@PathParam("id") String id) {
        return Response.ok("User: " + id).build();
    }

    // 这个方法不会被过滤器处理
    @GET
    @Path("/list")
    public Response getUserList() {
        return Response.ok("User List").build();
    }
}
  1. 注册动态绑定类:
    同样在Application子类中添加RegexFilterDynamicBinder.class,或者给它加@Provider注解。

注意事项:

  • 正则表达式尽量预编译(比如方案一中的static final Pattern),避免每次请求都重复编译,影响性能;
  • 使用requestContext.getUriInfo().getPath()获取路径时,会自动去掉应用的base URI,比直接拿请求URL更可靠;
  • 如果是ContainerResponseFilter,判断逻辑和请求过滤器完全一致,只需要在filter方法里先做URL匹配再执行逻辑。

内容的提问来源于stack exchange,提问作者Luciano Borges

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:46:06