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

Java 如何在ContainerResponseFilter中获取资源注释,java,http,rest,annotations,jersey,Java,Http,Rest,Annotations,Jersey,Jersey提供两个类与资源上的注释交互: ,一个类可以继承它,以便在应用程序启动时触发一次 ,几个类可以继承它们,以便在每次请求/响应时触发它们 ResourceFilterFactory定义了一个create方法(要实现),该方法采用AbstractMethod,该方法允许访问方法和类注释 ContainerRequestFilter和ContainerResponseFilter定义了一个filter方法(要实现),该方法接受请求/响应,但只允许访问被调用的方法注释,而不是类注释 我正

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

  • ,一个类可以继承它,以便在应用程序启动时触发一次
  • ,几个类可以继承它们,以便在每次请求/响应时触发它们
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<ResourceFilter> create(AbstractMethod method)
    {
        List<ResourceFilter> filters = newArrayList();
        if (isAnnotationPresent(method, CacheControl.class))
            filters.add(new CacheControlFilter(method));
        return filters;
    }

    private boolean isAnnotationPresent(AbstractMethod method, Class<? extends Annotation> clazz)
    {
        return method.isAnnotationPresent(clazz) || method.getResource().isAnnotationPresent(clazz);
    }
}

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


更新:还要注意,您不想为每个方法创建新实例。您只想对附加了@CacheControl注释或资源的方法执行此操作,对吗?此外,您还可以共享通用@CacheControl值的筛选器实例-即,如果一个方法使用与其他方法相同的缓存控制设置,请为此重用相同的筛选器,如果没有,请为该方法创建单独的筛选器实例。换句话说,您可以为每个不同的缓存控制设置一个筛选器,而不是为每个方法设置一个筛选器-因为您并不真正关心该方法-您关心附加到该方法的注释。

共享实例是我需要的轨迹;)
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<Object> 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.<Object> newArrayList(Splitter.on(',').split(header.toString()));
    }

    @Override
    public ContainerRequestFilter getRequestFilter()
    {
        return null;
    }

    @Override
    public ContainerResponseFilter getResponseFilter()
    {
        return this;
    }
}