Jersey:默认缓存控制到无缓存

在编写RESTful Web服务时,如果我在客户端(当前是.NET胖客户端)上启用任何类型的缓存,我会遇到问题。 默认情况下,Jersey不发送任何类型的缓存控制头,因此客户端会自动缓存大多数页面(这似乎是有效的行为)。

我想让Jersey默认发送一个“no-cache”的缓存控件,然后特别是响应覆盖缓存控件。

有没有办法和泽西这样做?

我发现RESTeasy能够使用@NoCache注释来指定整个类的设置,但我没有找到与Jersey类似的东西。

使用ResourceFilterFactory可以轻松使用Jersey – 您可以创建附加到方法的任何自定义注释来设置缓存控制设置。 在应用程序初始化时,为每个发现的资源方法调用ResourceFilterFactories – 在ResourceFilterFactory中,您可以检查该方法是否具有@CacheControlHeader注释(或者您想要调用它的任何内容) – 如果没有,只需返回添加“no-cache”的响应filter“指示响应,否则应使用注释中的设置。 以下是如何执行此操作的示例:

public class CacheFilterFactory implements ResourceFilterFactory { private static final List NO_CACHE_FILTER = Collections.singletonList(new CacheResponseFilter("no-cache")); @Override public List create(AbstractMethod am) { CacheControlHeader cch = am.getAnnotation(CacheControlHeader.class); if (cch == null) { return NO_CACHE_FILTER; } else { return Collections.singletonList(new CacheResponseFilter(cch.value())); } } private static class CacheResponseFilter implements ResourceFilter, ContainerResponseFilter { private final String headerValue; CacheResponseFilter(String headerValue) { this.headerValue = headerValue; } @Override public ContainerRequestFilter getRequestFilter() { return null; } @Override public ContainerResponseFilter getResponseFilter() { return this; } @Override public ContainerResponse filter(ContainerRequest request, ContainerResponse response) { // attache Cache Control header to each response based on the annotation value response.getHttpHeaders().putSingle(HttpHeaders.CACHE_CONTROL, headerValue); return response; } } } 

注释可以如下所示:

 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface CacheControlHeader { String value(); } 

通过将以下init参数添加到web.xml中Jersey servlet的定义,可以在应用程序中注册ResourceFilterFactory:

  com.sun.jersey.spi.container.ResourceFilters package.name.CacheFilterFactory  

基于@ martin-matula的解决方案,我创建了两个Cache注释。 一个@NoCache完全没有缓存,一个@CacheMaxAge用于特定缓存。 CacheMaxAge有两个参数,因此您不必自己计算秒数:

 @GET @CacheMaxAge(time = 10, unit = TimeUnit.MINUTES) @Path("/awesome") public String returnSomethingAwesome() { ... } 

ResourceFilter现在有这个create方法,默认情况下不会干扰(所以其他缓存机制继续工作):

 @Override public List create(AbstractMethod am) { if (am.isAnnotationPresent(CacheMaxAge.class)) { CacheMaxAge maxAge = am.getAnnotation(CacheMaxAge.class); return newCacheFilter("max-age: " + maxAge.unit().toSeconds(maxAge.time())); } else if (am.isAnnotationPresent(NoCache.class)) { return newCacheFilter("no-cache"); } else { return Collections.emptyList(); } } private List newCacheFilter(String content) { return Collections . singletonList(new CacheResponseFilter(content)); } 

您可以在我的博文中看到完整的解决方案。

谢谢马丁的解决方案!

@ martin-matula的解决方案不适用于JAX-RS 2.0 / Jersey 2.x,因为ResourceFilterFactory和ResourceFilter已被删除。 该解决方案可以如下适用于JAX-RS 2.0。

注解:

 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface CacheControlHeader { String value(); } 

DynamicFeature:

 @Provider public class CacheFilterFactory implements DynamicFeature { private static final CacheResponseFilter NO_CACHE_FILTER = new CacheResponseFilter("no-cache"); @Override public void configure(ResourceInfo resourceInfo, FeatureContext featureContext) { CacheControlHeader cch = resourceInfo.getResourceMethod() .getAnnotation(CacheControlHeader.class); if (cch == null) { featureContext.register(NO_CACHE_FILTER); } else { featureContext.register(new CacheResponseFilter(cch.value())); } } private static class CacheResponseFilter implements ContainerResponseFilter { private final String headerValue; CacheResponseFilter(String headerValue) { this.headerValue = headerValue; } @Override public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) { // attache Cache Control header to each response // based on the annotation value containerResponseContext .getHeaders() .putSingle(HttpHeaders.CACHE_CONTROL, headerValue); } } } 

CacheFilterFactory需要在Jersey注册。 我是通过Dropwizard来做的 – 使用environment.jersey()。register() – 但是在独立系统上,我理解这可以通过让Jersey通过在web.xml中定义以下内容来扫描类的@Provider注释来完成。 :

  my.package.MyApplication org.glassfish.jersey.servlet.ServletContainer   jersey.config.server.provider.packages my.package   

有关注册组件的更多信息,请参阅此文章 。

我想你可以使用

 isNoCache(true) 

这将停止在浏览器中缓存。

看到:

http://jersey.java.net/nonav/apidocs/1.12/jersey/javax/ws/rs/core/CacheControl.html#isNoCache%28%29

希望这可以帮助。

我发现了一个可以禁用缓存的注释。 您可以对API使用以下注释:

 @CacheControl(noCache = true) 

参考: 缓存控制的Jersey注释