如何从泽西过滤器中排除一些网址?

时间:2016-09-05 10:46:39

标签: java web-services filter jersey

我用jersey来创建webservices。我使用ContainerRequestFilter创建了请求过滤器。我已经完成了Jersey Request Filter only on certain URI个问题,但我想排除某些网址的过滤器。

@Provider
public class AuthFilter implements ContainerRequestFilter{

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

// business logic

   }
}

3 个答案:

答案 0 :(得分:18)

名称绑定过滤器

您可以考虑使用名称绑定过滤器来选择过滤器绑定到的端点,而不是从全局过滤器中排除URI。

另请查看this answer以获取名称绑定过滤器的一些示例。

全局过滤器

如果您对全局过滤方法仍然满意,可以考虑使用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();
          ...
      }
      
    2. 获得UriInfo实例后,您将可以访问一些可能有用的方法:

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

      如果请求的URI与您要应用过滤器的URI不匹配,只需使用return指令:

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

      动态绑定

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

      Jersey documentation中提取的以下示例显示了如何实现动态绑定:

      @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接口的提供程序完成绑定。该接口定义了一个configure方法,其中包含两个参数ResourceInfoFeatureContext

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

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

      请注意,使用动态绑定注册的过滤器和拦截器只是为资源方法运行的其他过滤器。如果有任何名称绑定提供者或全局提供者,他们仍将被执行。

      有关详细信息,请查看Jersey documentation about filters and interceptors

答案 1 :(得分:1)

使用@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;
    }
}

正如其他人所提到的,可以使用动态绑定,但它非常难看,因为过滤器不适用于所有资源并不明显。

答案 2 :(得分:-1)

可能您可以使用getUri

检查网址格式并中止请求

类似于以下内容

public class AuthFilter implements ContainerRequestFilter{

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

       String path =    requestContext.getUriInfo().getPath();
       if(path.contains("admin")){
          requestContext.abortWith(new Response());
       }

   }
}

https://jersey.java.net/documentation/latest/filters-and-interceptors.html#d0e9767