如何在Jersey ContainerResponseFilter中获取资源注释

Jersey提供两个类来与资源上的注释进行交互:

  • ResourceFilterFactory ,一个类可以inheritance它,以便在应用程序启动时触发一次
  • ContainerRequestFilter , ContainerResponseFilter ,几个类可以inheritance它们以在每个请求/响应上触发它们

ResourceFilterFactory定义了一个create方法(实现),它采用AbstractMethod来提供对方法和类注释的访问。

ContainerRequestFilter和ContainerResponseFilter定义了一个filter方法(实现),它接受请求/响应,但那些只能访问被调用的方法注释,而不是第一类。

我正在尝试实现一个CacheControl注释,它以下列方式定义HTTP缓存头。

 @Path("/path") @CacheControl(maxAge = 172800) public class Resource { @GET @Path("/{id}") @CacheControl(mustRevalidate = true) public Response get(@PathParam("id") Long id) { ... } } 

我的问题是我不想为我的应用程序中定义的每个REST方法创建一个新的CacheControlFilter

 public class FilterFactory implements ResourceFilterFactory { @Override public List create(AbstractMethod method) { List filters = newArrayList(); if (isAnnotationPresent(method, CacheControl.class)) filters.add(new CacheControlFilter(method)); return filters; } private boolean isAnnotationPresent(AbstractMethod method, Class clazz) { return method.isAnnotationPresent(clazz) || method.getResource().isAnnotationPresent(clazz); } } 

有没有办法访问AbstractMethod而不为每个REST方法实例化CacheContronlFilter?

 public class CacheControlFilter implements ResourceFilter, ContainerResponseFilter { private AbstractMethod method; public CacheControlFilter(AbstractMethod method) { this.method = method; } @Override public ContainerResponse filter(ContainerRequest request, ContainerResponse response) { putCacheControlIfExists(response, method.getAnnotations()); putCacheControlIfExists(response, method.getResource().getAnnotations()); return response; } private void putCacheControlIfExists(ContainerResponse response, Annotation[] annotations) { CacheControl annotation = findCacheControl(annotations); if (annotation != null) response.getHttpHeaders().put(CACHE_CONTROL, createCacheControlHeader(annotation)); } private CacheControl findCacheControl(Annotation[] annotations) { for (Annotation annotation : annotations) if (annotation instanceof CacheControl) return (CacheControl) annotation; return null; } private List createCacheControlHeader(CacheControl annotation) { javax.ws.rs.core.CacheControl header = new javax.ws.rs.core.CacheControl(); header.setMaxAge(annotation.maxAge()); header.setMustRevalidate(annotation.mustRevalidate()); header.setNoCache(annotation.noCache()); header.setNoStore(annotation.noStore()); header.setNoTransform(annotation.noTransform()); header.setProxyRevalidate(annotation.proxyRevalidate()); return Lists. newArrayList(Splitter.on(',').split(header.toString())); } @Override public ContainerRequestFilter getRequestFilter() { return null; } @Override public ContainerResponseFilter getResponseFilter() { return this; } } 

为什么对每个适用的方法都没有单独的filter实例很重要? 可能存在大量并发访问,因此如果您不希望这些是单独的实例,则它们必须是可变的并且您必须进入threadlocals混乱(以存储当前适用于给定线程的抽象方法) )。 不确定这是不是你真正想要的。 每个单独的对象并不昂贵。

更新:另请注意,您不希望为每个方法创建新实例。 您只想为附加了@CacheControl注释或其资源的方法执行此操作,对吧? 您还可以共享公共@CacheControl值的filter实例 – 即,如果某个方法使用与其他方法相同的缓存控制设置,请为此重用相同的filter,否则,为该方法创建一个单独的filter实例。 换句话说 – 每个不同的缓存控制设置可以有一个filter,而不是每个方法一个filter – 因为您并不真正关心该方法 – 您关心附加到它的注释。