如何从球衣过滤器中排除一些网址?

2022-09-03 04:18:41

我使用球衣来创建Web服务。我已使用 创建了请求筛选器。我只在某些URI问题上浏览了泽西岛请求过滤器,但我只想排除某些网址的过滤器。ContainerRequestFilter

@Provider
public class AuthFilter implements ContainerRequestFilter{

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

// business logic

   }
}

答案 1

名称绑定筛选器

可以考虑使用名称绑定筛选器来选择筛选器将绑定到的终结点,而不是从全局筛选器中排除 URI。

另请查看此答案,了解名称绑定筛选器的一些示例。

全局筛选器

如果对全局筛选器方法仍然满意,可以考虑使用 UriInfo 接口获取有关所请求的 URI 的详细信息。使用以下方法之一获取 UriInfo 的实例:

  1. 使用@Context注释:

    @Provider
    public class AuthFilter implements ContainerRequestFilter {
    
        @Context
        private UriInfo info;
    
        @Override
        public void filter(ContainerRequestContext requestContext) throws IOException {
            ...
        }
    }
    
  1. ContainerRequestContext 获取它:

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        UriInfo info = requestContext.getUriInfo();
        ...
    }
    

拥有实例后,您将可以访问一堆可能有用的方法:UriInfo

有关更多详细信息,请查看 UriInfo 文档。

如果请求的 URI 与要应用筛选器的 URI 不匹配,只需使用说明:return

@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
    UriInfo info = requestContext.getUriInfo();
    if (!info.getPath().contains("secured")) {
        return;
    }
}

动态绑定

另一种方法是动态绑定。它允许您以动态方式将筛选器和拦截器分配给资源方法。上面提到的名称绑定使用静态方法,对绑定的更改需要更改源代码和重新编译。使用动态绑定,可以实现在应用程序初始化期间定义绑定的代码。

Jersey 文档中提取的以下示例演示如何实现动态绑定:

@Path("helloworld")
public class HelloWorldResource {

    @GET
    @Produces("text/plain")
    public String getHello() {
        return "Hello World!";
    }

    @GET
    @Path("too-much-data")
    public String getVeryLongString() {
        String str = ... // very long string
        return str;
    }
}
// This dynamic binding provider registers GZIPWriterInterceptor
// only for HelloWorldResource and methods that contain
// "VeryLongString" in their name. It will be executed during
// application initialization phase.
public class CompressionDynamicBinding implements DynamicFeature {

    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext context) {
        if (HelloWorldResource.class.equals(resourceInfo.getResourceClass())
                && resourceInfo.getResourceMethod().getName().contains("VeryLongString")) {
            context.register(GZIPWriterInterceptor.class);
        }
    }
}

绑定是使用实现 DynamicFeature 接口的提供程序完成的。该接口定义了一个具有两个参数的方法,ResourceInfoFeatureContextconfigure

ResourceInfo 包含有关可以执行绑定的资源和方法的信息。配置方法将针对应用程序中定义的每个资源方法执行一次。在上面的示例中,提供程序将执行两次,一次用于方法,一次用于(一次将包含有关方法的信息,一次它将指向 )。getHello()getVeryLongString()resourceInfogetHello()getVeryLongString()

如果动态绑定提供程序想要为实际的资源方法注册任何提供程序,它将使用提供的 FeatureContext 来执行此操作,该 FeatureContext 扩展了 JAX-RS 可配置 API。可以使用所有用于注册筛选器或侦听器类或实例的方法。此类动态注册的筛选器或拦截器将仅绑定到实际的资源方法。在上面的示例中,将仅绑定到将导致仅针对此方法而不是方法压缩数据的方法。GZIPWriterInterceptorgetVeryLongString()getHello()

请注意,使用动态绑定注册的筛选器和侦听器只是为资源方法运行的附加筛选器。如果存在任何名称绑定提供程序或全局提供程序,它们仍将被执行。


有关更多详细信息,请查看泽西岛有关过滤器和拦截器的文档


答案 2

使用@NameBinding可能是最优雅的方法,但如果您只想排除单个资源并对所有其他资源应用筛选器,则必须记住将绑定批注放在所有资源上。在这种情况下,您可以使用 来检查目标资源是否已匹配。这比对可能更改的路径进行硬编码要好。ContainerRequestContext.getUriInfo().getMatchedResources()

下面的示例将对除 StatusResource 之外的所有资源应用筛选器逻辑:

public class CorsContainerRequestFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext req) {
        if (!matchesStatusResource(req)) {
            // filter logic
        }
    }

    private boolean matchesStatusResource(ContainerRequestContext req) {
        List<Object> matchedResources = req.getUriInfo().getMatchedResources();
        for (Object matchedResource : matchedResources) {
            if (matchedResource instanceof StatusResource) {
                return true;
            }
        }
        return false;
    }
}

正如其他人所提到的,动态绑定可以代替使用,但它非常丑陋,因为很明显过滤器不会应用于所有资源。


推荐