2013-02-26 54 views
7

我正在嘗試開發使用澤西的restful API。我有一個特定的獲取操作的GET API我的GET從相同的客戶端採取相同的時間。 是否可以緩存響應?任何指針表示讚賞。如何緩存Jersey的響應?

感謝

回答

10

您可以使用CacheControl,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

+0

ü介意解釋爲什麼ü禁用緩存控制(無緩存)? 它就像說:沒有緩存可能,但看看這裏我有一個無用的Etag和Last-Modified頭。 – Orri 2013-11-12 17:50:05

+2

這是說,它的永久緩存,但服務器可以說資源是否被修改基於電子標籤,因此客戶端/瀏覽器可以使用它從緩存 – TheWhiteRabbit 2013-11-13 09:18:12

3

你可以與新澤西一起使用適用於標準的java任何緩存機制,像Ehcache

您只需要注意驗證後端數據沒有變化。

下面是簡單的例子與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

解決方案的概要:

  1. Request作爲方法參數

    接口:

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

    實現:

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

    缺點:

    • 實現細節Request暴露

    • 返回類型Reponse是通用

    • 缺少返回類型的語法在WADL

    • client proxy不必要參數Request

  2. Request作爲實例變量

    接口:

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

    實現:

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

    缺點:

  3. ShallowEtagHeaderFilter如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> 
    

    接口:

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

    實現:

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

    缺點:

    • 壞服務器的性能,看看JavaDoc

      只有在提交響應
    • 作品

    • 不支持的weak ETag

  4. 定製WriterInterceptorJAX-RS Interceptor

    攔截:

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

    另請參見:ServerCacheInterceptor(RestEasy的)

    接口:

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

    實現:

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

    缺點:

    • 沒有預定義的攔截器澤西可用

    • 壞服務器性能

    • 不支持的weak ETag

    • 醜陋的解決方法與WebApplicationException