2011-11-29 45 views
9

新澤西提供兩類資源與註釋交互:我怎樣才能獲得資源的註釋在新澤西ContainerResponseFilter

ResourceFilterFacto ry定義了一個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); 
    } 
} 

是否有訪問AbstractMethod沒有實例化一個CacheContronlFilter每一個REST方法的方法嗎?

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; 
    } 
} 

回答

4

爲什麼是重要的沒有過濾器的一個單獨的實例爲每一個應用的方法?可能有很多併發訪問,所以如果你不希望這些是單獨的實例,它們必須是可變的,並且你將不得不進入threadlocals混亂(存儲當前適用於給定線程的抽象方法)。不知道這是你真正想要的。爲每個單獨的對象並不昂貴。

更新:另請注意,您不想爲創建一個新的實例,每個方法。你只是想爲它們附加任何@CacheControl註解或其資源的方法來做,對吧?您也可以共享常用@CacheControl值的過濾器實例 - 即,如果某個方法使用與其他方法相同的緩存控制設置,則爲該方法重用相同的過濾器,如果不是,則爲該方法創建單獨的過濾器實例。換句話說 - 每個獨立的緩存控制設置都可以有一個過濾器,而不是每個方法都有一個過濾器 - 因爲您並不在乎該方法 - 而是關心附加在它上面的註釋。

+0

共享實例是我需要的軌道;) –