简体   繁体   English

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

[英]How can I get resource annotations in a Jersey ContainerResponseFilter

Jersey offers two classes to interact with annotations on resources: Jersey提供两个类来与资源上的注释进行交互:

ResourceFilterFactory defines a create method (to implement) that take an AbstractMethod which gives access to methods and classes annotations. ResourceFilterFactory定义了一个create方法(实现),它采用AbstractMethod来提供对方法和类注释的访问。

ContainerRequestFilter and ContainerResponseFilter defines a filter method (to implement) that take request/response but those give solely access to the called method annotation, not the class one. ContainerRequestFilter和ContainerResponseFilter定义了一个filter方法(实现),它接受请求/响应,但那些只能访问被调用的方法注释,而不是第一类。

I'm trying to implement a CacheControl annotation that defines HTTP cache headers the following way. 我正在尝试实现一个CacheControl注释,它以下列方式定义HTTP缓存头。

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

My problem is that I don't want to create a new CacheControlFilter for every REST method defined in my application . 我的问题是我不想为我的应用程序中定义的每个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);
    }
}

Is there a way to access the AbstractMethod without instancing a CacheContronlFilter for every REST method? 有没有办法访问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<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;
    }
}

Why is it important to not have a separate instance of the filter for every applicable method? 为什么对每个适用的方法都没有单独的过滤器实例很重要? There may be a lot of concurrent access, so if you don't want these to be separate instances, they would have to be mutable and you would have to get into the threadlocals mess (to store the abstract method currently applicable for the given thread). 可能有很多并发访问,所以如果你不希望这些是单独的实例,它们必须是可变的,你必须进入threadlocals混乱(存储当前适用于给定线程的抽象方法) )。 Not sure if that's what you really want. 不确定这是不是你真正想要的。 Having a separate object for each is not that expensive. 每个都有一个单独的对象并不昂贵。

UPDATE: Also note, you don't want to create a new instance for every method. 更新:另请注意,您不希望为每个方法创建新实例。 You just want to do it for methods with any @CacheControl annotation attached to them or to their resources, right? 您只想对附加了@CacheControl注释或其资源的方法执行此操作,对吧? Also you can share filter instances for common @CacheControl values - ie if a method uses the same cache control setting as some other method, reuse the same filter for that, if not, create a separate instance of the filter for that method. 您还可以共享公共@CacheControl值的过滤器实例 - 即,如果某个方法使用与其他方法相同的缓存控制设置,请为此重用相同的过滤器,否则,为该方法创建一个单独的过滤器实例。 In other words - you can have one filter per one distinct cache-control setting as opposed to one filter per method - as you don't really care about the method - you care about the annotations attached to it. 换句话说 - 每个不同的缓存控制设置可以有一个过滤器,而不是每个方法一个过滤器 - 因为您并不真正关心该方法 - 您关心附加到它的注释。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM