2011-11-29 12 views
9

Jersey ofrece dos clases de interactuar con anotaciones sobre los recursos:¿Cómo puedo obtener anotaciones de recursos en un jersey ContainerResponseFilter

ResourceFilterFacto ry define un método create (implementar) que toma un AbstractMethod que da acceso a anotaciones de métodos y clases.

ContainerRequestFilter y ContainerResponseFilter define un método filter (implementar) que toma la solicitud/respuesta pero que da acceso únicamente a la anotación de método llamado, no la clase uno.

estoy tratando de poner en práctica una anotación CacheControl que define cabeceras de caché HTTP de la siguiente manera.

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

Mi problema es que yo no quiero crear un nuevo CacheControlFilter para cada método RESTO definido en mi solicitud.

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

¿Hay una manera de acceder al AbstractMethod sin generar ejemplares de un CacheContronlFilter para cada método de reposo?

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

Respuesta

4

¿Por qué es importante no tener una instancia independiente del filtro para cada método aplicable? Puede haber un gran número de accesos concurrentes, por lo que si no quieres que sean instancias separadas, tendrían que ser mutables y tendrías que entrar al desorden threadlocals (para almacenar el método abstracto actualmente aplicable para el hilo dado)) No estoy seguro si eso es lo que realmente quieres. Tener un objeto separado para cada uno no es tan caro.

ACTUALIZACIÓN: También tenga en cuenta que no desea crear una nueva instancia para cada método. Solo quiere hacerlo para métodos con cualquier anotación de @CacheControl adjunta a ellos o a sus recursos, ¿verdad? También puede compartir instancias de filtro para valores comunes de @CacheControl; es decir, si un método usa la misma configuración de control de caché que otro método, reutilice el mismo filtro para eso, de lo contrario, cree una instancia separada del filtro para ese método. En otras palabras, puede tener un filtro por cada configuración distinta de control de caché en lugar de un filtro por método, ya que realmente no le importa el método; le importan las anotaciones adjuntas.

+0

Compartir instancias es la pista que necesitaba;) –

Cuestiones relacionadas