2013-02-26 6 views
7

Ich versuche, Restful API mit Jersey zu entwickeln.Ich habe GET APIs für eine bestimmte get-Operation mein GET nimmt die gleiche Zeit vom gleichen Client. Ist es möglich, die Antwort im Cache zu speichern? Irgendwelche Zeiger werden geschätzt.Wie Cache Antwort mit Jersey?

Dank

Antwort

10

Sie Cachecontrol verwenden können, ETAG -

// In your jersey method 
    final EntityTag eTag = new EntityTag(resource.getId() + "_" + 
    resource.getLastModified().getTime()); 
    final CacheControl cacheControl = new CacheControl(); 
    cacheControl.setMaxAge(-1); 

    ResponseBuilder builder = request.evaluatePreconditions(
     resource.getLastModified(), eTag); 

    // the resoruce's information was modified, return it 
    if (builder == null) { 
     builder = Response.ok(resource); 
    } 

    // the resource's information was not modified, return a 304 

    return builder.cacheControl(cacheControl).lastModified(
     resource.getLastModified()).tag(eTag).build(); 

resource mit der Ressourcen-Instanz ersetzen unten Beispielcode folgen.

+0

Würde u erklären dagegen, warum u Cache-Control (no-cache) deaktivieren? Es ist wie zu sagen: sry kein Caching möglich, aber sieh hier habe ich einen nutzlosen Etag und Last-Modified-Header. – Orri

+2

es ist zu sagen, es ist für immer im Cache gespeichert, aber der Server kann sagen, ob die Ressource basierend auf E-Tag geändert wird, daher Client/Browser kann es aus dem Cache verwenden – TheWhiteRabbit

3

Sie könnten jeden Caching-Mechanismus anwendbar für Standard-Java zusammen mit Jersey verwenden, wie Ehcache.

Sie müssen nur darauf achten, dass sich Ihre Daten im Backend nicht geändert haben.

Hier ist einfaches Beispiel mit Ehcache:

@GET 
@Path("{id}") 
public List<Data> getData(@PathParam("id") Long id) { 
    Element element = CacheManager.getInstance().getCache("test").get(id); 
    if(element == null) { 
     Data value = fetchElementFromBackend(id); 
     CacheManager.getInstance().getCache("test").put(new Element(id, value)); 
     return value; 
    } 

    return element.getObjectValue(); 
} 
5

Zusammenfassung der Lösungen:

  1. Request als Methodenparameter

    Schnittstelle:

    @Path("myentity") 
    public interface MyEntityResource 
    
        @GET 
        @Produces(MediaType.APPLICATION_JSON) 
        public Response getMyEntity(@Context final Request request); 
    } 
    

    Umsetzung:

    public class MyEntityResourceImpl implements MyEntityResource 
    
        @Override 
        public Response getMyEntity(final Request request) { 
    
         final MyEntity myEntity = ... // load entity 
         final String eTagValue = ... // calclutate value of ETag 
    
         final EntityTag eTag = new EntityTag(eTagValue); 
    
         ResponseBuilder responseBuilder = request.evaluatePreconditions(eTag); 
    
         if (responseBuilder == null) { 
          return Response.ok(user).tag(eTag).build(); 
         } 
    
         return responseBuilder.build(); 
        } 
    } 
    

    Nachteile:

    • Implementierung Detail Request wird

    • ausgesetzt
    • Rückgabetyp Reponse generic ist

    • Grammatik der Rückgabetyp in WADL

    • client proxy mit unnötigen Parameter fehlt Request

  2. Request als Instanzvariable

    Schnittstelle:

    @Path("myentity") 
    public interface MyEntityResource 
    
        @GET 
        @Produces(MediaType.APPLICATION_JSON) 
        public Response getMyEntity(); 
    } 
    

    Umsetzung:

    public class MyEntityResourceImpl implements MyEntityResource 
    
        @Context 
        private Request request 
    
        @Override 
        public Response getMyEntity() { 
    
         final MyEntity myEntity = ... // load entity 
         final String eTagValue = ... // calclutate value of ETag 
    
         final EntityTag eTag = new EntityTag(eTagValue); 
    
         ResponseBuilder responseBuilder = request.evaluatePreconditions(eTag); 
    
         if (responseBuilder == null) { 
          return Response.ok(user).tag(eTag).build(); 
         } 
    
         return responseBuilder.build(); 
        } 
    } 
    

    Nachteile:

  3. ShallowEtagHeaderFilter als Webfilter

    Web.xml:

    <filter> 
        <filter-name>etagFilter</filter-name> 
        <filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class> 
    </filter> 
    <filter-mapping> 
        <filter-name>etagFilter</filter-name> 
        <url-pattern>/api/*</url-pattern> 
    </filter-mapping> 
    

    Schnittstelle:

    @Path("myentity") 
    public interface MyEntityResource 
    
        @GET 
        @Produces(MediaType.APPLICATION_JSON) 
        public MyEntity getMyEntity(); 
    } 
    

    Umsetzung:

    public class MyEntityResourceImpl implements MyEntityResource 
    
        @Override 
        public MyEntity getMyEntity() { 
    
         final MyEntity myEntity = ... // load entity 
         return myEntity; 
        } 
    } 
    

    Nachteile:

    • schlechte Serverleistung finden JavaDoc

    • funktioniert nur auf uncommitted Antwort

    • keine Unterstützung von weak ETag

  4. Individuelle WriterInterceptor als JAX-RS Interceptor

    Interceptor: auch

    public class CustomInterceptor implements WriterInterceptor { 
    
        @Context 
        private Request request; 
    
        @Override 
        public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { 
    
         OutputStream old = context.getOutputStream(); 
    
         ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 
    
         try { 
    
          context.setOutputStream(buffer); 
          context.proceed(); 
    
          byte[] entity = buffer.toByteArray(); 
    
          String etag = ... // calclutate value of ETag 
          context.getHeaders().putSingle(HttpHeaders.ETAG, etag); 
    
          ResponseBuilder responseBuilder = request.evaluatePreconditions(eTag); 
    
          if (responseBuilder == null) { 
           throw new WebApplicationException(responseBuilder.status(Response.Status.NOT_MODIFIED).header(HttpHeaders.ETAG, etag).build()); 
          } 
    
          old.write(entity); 
    
         } finally { 
          context.setOutputStream(old); 
         } 
        } 
    } 
    

    See: ServerCacheInterceptor (Resteasy)

    Schnittstelle:

    @Path("myentity") 
    public interface MyEntityResource 
    
        @GET 
        @Produces(MediaType.APPLICATION_JSON) 
        public MyEntity getMyEntity(); 
    } 
    

    Umsetzung:

    public class MyEntityResourceImpl implements MyEntityResource 
    
        @Override 
        public MyEntity getMyEntity() { 
    
         final MyEntity myEntity = ... // load entity 
         return myEntity; 
        } 
    } 
    

    Nachteile:

    • keine vordefinierte Abfangjäger für Jersey verfügbar

    • schlechte Serverleistung

    • keine Unterstützung von weak ETag

    • hässlich Abhilfe mit WebApplicationException