[英]Jersey: Default Cache Control to no-cache
在編寫RESTful Web服務時,如果我在客戶端(當前是.NET胖客戶端)上啟用任何類型的緩存,我會遇到問題。 默認情況下,Jersey不發送任何類型的緩存控制頭,因此客戶端會自動緩存大多數頁面(這似乎是有效的行為)。
我想讓Jersey默認發送一個“no-cache”的緩存控件,然后特別是響應覆蓋緩存控件。
有沒有辦法和澤西這樣做?
我發現RESTeasy能夠使用@NoCache注釋來指定整個類的設置,但我沒有找到與Jersey類似的東西。
使用ResourceFilterFactory可以輕松使用Jersey - 您可以創建附加到方法的任何自定義注釋來設置緩存控制設置。 在應用程序初始化時,為每個發現的資源方法調用ResourceFilterFactories - 在ResourceFilterFactory中,您可以檢查該方法是否具有@CacheControlHeader注釋(或者您想要調用它的任何內容) - 如果沒有,只需返回添加“no-cache”的響應過濾器“指示響應,否則應使用注釋中的設置。 以下是如何執行此操作的示例:
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();
}
通過將以下init參數添加到web.xml中Jersey servlet的定義,可以在應用程序中注冊ResourceFilterFactory:
<init-param>
<param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
<param-value>package.name.CacheFilterFactory</param-value>
</init-param>
根據@ martin-matula的解決方案,我創建了兩個Cache注釋。 一個@NoCache
根本沒有緩存,一個@CacheMaxAge
用於特定緩存。 CacheMaxAge
有兩個參數,因此您不必自己計算秒數:
@GET
@CacheMaxAge(time = 10, unit = TimeUnit.MINUTES)
@Path("/awesome")
public String returnSomethingAwesome() {
...
}
ResourceFilter現在有這個create方法,默認情況下不會干擾(所以其他緩存機制繼續工作):
@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));
}
您可以在我的博文中看到完整的解決方案。
謝謝馬丁的解決方案!
@ 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注釋來完成。 :
<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>
有關注冊組件的更多信息,請參閱此文章 。
我想你可以用
isNoCache(true)
這將停止在瀏覽器中緩存。
看到:
http://jersey.java.net/nonav/apidocs/1.12/jersey/javax/ws/rs/core/CacheControl.html#isNoCache%28%29
希望這可以幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.