2011-11-29 6 views
9

Jersey offre due classi di interagire con annotazioni sulle risorse:Come posso ottenere le annotazioni di risorse in un Jersey ContainerResponseFilter

ResourceFilterFacto ry definisce un metodo create (da implementare) che prende uno AbstractMethod che dà accesso alle annotazioni di metodi e classi.

ContainerRequestFilter e ContainerResponseFilter definisce un metodo filter (da implementare) che richiede la richiesta/risposta ma che dà solo l'accesso all'annotazione del metodo chiamato, non quella di classe.

Sto tentando di implementare un'annotazione CacheControl che definisce le intestazioni della cache HTTP nel seguente modo.

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

Il mio problema è che io non voglio creare un nuovo CacheControlFilter per ogni metodo REST definito nella mia applicazione.

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

Esiste un modo per accedere al AbstractMethod senza instancing un CacheContronlFilter per ogni metodo 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; 
    } 
} 

risposta

4

Perché è importante non avere un'istanza separata del filtro per ogni metodo applicabile? Potrebbero esserci molti accessi concorrenti, quindi se non vuoi che queste siano istanze separate, dovrebbero essere modificabili e dovresti entrare nel caos di threadlocals (per memorizzare il metodo astratto attualmente applicabile per il thread specificato). Non sono sicuro se è quello che vuoi veramente. Avere un oggetto separato per ciascuno non è così costoso.

AGGIORNAMENTO: Si noti inoltre che non si desidera creare una nuova istanza per il metodo ogni. Vuoi solo farlo per i metodi con qualsiasi annotazione @CacheControl associata a loro o alle loro risorse, giusto? Inoltre è possibile condividere istanze di filtro per i valori comuni di @CacheControl, ad esempio se un metodo utilizza la stessa impostazione di controllo della cache di un altro metodo, riutilizzare lo stesso filtro, altrimenti creare un'istanza separata del filtro per tale metodo. In altre parole, è possibile avere un filtro per ogni impostazione di controllo della cache distinta rispetto a un filtro per metodo, poiché non ti interessa il metodo, ti interessano le annotazioni ad esso associate.

+0

Le istanze di condivisione sono la traccia di cui avevo bisogno;) –

Problemi correlati