新泽西州:默认缓存控制为no-cache(Jersey: Default Cache Control

2019-06-25 07:30发布

在写一个RESTful Web服务,我遇到的问题,如果我让我的客户端上的任何形式的缓存(目前是一个.NET胖客户端)。 默认情况下,新泽西州不发送任何形式的缓存控制头的,所以客户端会自动缓存大部分页面(这似乎是有效的行为)。

我想有泽西默认情况下发送“无缓存”的高速缓存控制,然后在特定的反应覆盖缓存控制。

有没有什么办法与新泽西做到这一点?

我发现RestEasy的必须使用@NoCache批注指定全班设置的能力,但我还没有发现与新泽西类似的事情。

Answer 1:

这是通过使用ResourceFilterFactory容易新泽西 - 您可以创建连接到你的方法来设置缓存控制设置任何自定义注释。 ResourceFilterFactories被调用每个已发现资源的方法,当应用程序初始化 - 在你ResourceFilterFactory您可以检查方法有你@CacheControlHeader注释(或任何你想将它命名) - 如果不是,简单地返回响应滤波器,增加了“无缓存“指令的响应,否则它应该从注释使用的设置。 这里是如何做到这一点的例子:

public class CacheFilterFactory implements ResourceFilterFactory {
    private static final List<ResourceFilter> NO_CACHE_FILTER = Collections.<ResourceFilter>singletonList(new CacheResponseFilter("no-cache"));

    @Override
    public List<ResourceFilter> create(AbstractMethod am) {
        CacheControlHeader cch = am.getAnnotation(CacheControlHeader.class);
        if (cch == null) {
            return NO_CACHE_FILTER;
        } else {
            return Collections.<ResourceFilter>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();
}

该ResourceFilterFactory可以在应用程序中加入下面的初始参数web.xml中的servlet新泽西州的定义进行注册:

<init-param>
    <param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
    <param-value>package.name.CacheFilterFactory</param-value>
</init-param>


Answer 2:

基于由@马丁 - matula的解决方案,我创建了两个缓存的注释。 一个@NoCache在所有的无缓存和一个@CacheMaxAge特定的缓存。 该CacheMaxAge有两个参数,这样你就不必自己计算秒:

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

该ResourceFilter现在有这个创建默认不干预(所以其他的缓存机制,保持工作)方法:

@Override
public List<ResourceFilter> 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<ResourceFilter> newCacheFilter(String content) {
    return Collections
            .<ResourceFilter> singletonList(new CacheResponseFilter(content));
}

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

感谢您的解决方案马丁!



Answer 3:

@马丁 - matula的解决方案不与JAX-RS 2.0的工作/新泽西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需要与泽西岛注册。 我通过Dropwizard这样做 - 使用environment.jersey()寄存器() - 但在独立系统上我明白这一点例如可以通过让新泽西扫描您的类注释@Provider通过定义在web.xml以下完成:

<servlet>
    <servlet-name>my.package.MyApplication</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

    <!-- Register resources and providers under my.package. -->
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>my.package</param-value>
    </init-param>
</servlet>

见这个职位有关注册组件的详细信息。



Answer 4:

我想你可以使用

isNoCache(true)

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

看到:

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

希望这可以帮助。



Answer 5:

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

@CacheControl(noCache = true)

参考: 新泽西注释缓存控制



文章来源: Jersey: Default Cache Control to no-cache