【发布时间】:2013-11-18 16:20:04
【问题描述】:
在 Dropwizard 服务中设置静态资产的缓存控制标头的最佳方法是什么?
一些谷歌搜索显示了一个 AssetsBundle 构造函数:
但是,经过进一步调查,com.yammer.dropwizard.bundles 包似乎从 5.1 版开始就不再是 Dropwizard 的一部分了。
也许我遗漏了一些明显的东西,但有没有更好的方法来处理这个问题?
【问题讨论】:
在 Dropwizard 服务中设置静态资产的缓存控制标头的最佳方法是什么?
一些谷歌搜索显示了一个 AssetsBundle 构造函数:
但是,经过进一步调查,com.yammer.dropwizard.bundles 包似乎从 5.1 版开始就不再是 Dropwizard 的一部分了。
也许我遗漏了一些明显的东西,但有没有更好的方法来处理这个问题?
【问题讨论】:
如果有人感兴趣(从这个问题的浏览量来看,他们可能没有)这就是我解决这个问题的方法。
我在与我的服务类相同的包中创建了一个 CacheControlFilter 类:
public class CacheControlFilter implements Filter{
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse) response;
// Add whatever headers you want here
resp.setHeader("Cache-Control", "public, max-age=500000");
resp.setHeader("Expires", new Date().getTime()+500000 + "");
chain.doFilter(request, response);
}
public void destroy() {}
public void init(FilterConfig arg0) throws ServletException {}
}
然后在服务类中,添加一行:
env.addFilter(new CacheControlFilter(), "/*");
当然,您可以更细粒度地为图像文件和 css 文件添加不同的过滤器,但这会为所有请求添加标头。
来自评论:
对于 dropwizard 1.0.6。只需注册
env.servlets()
.addFilter("MyFilter", new CacheControlFilter())
.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*")
【讨论】:
基于 Tim Barclay 的回答,如果请求的资源是扩展名为 js、css、png、jpg、gif 或 svg 的文件,我创建了一个过滤器,将 Cache-Control 和 Expires 设置为未来一年.否则缓存被禁用。
希望对某人有所帮助!
protected void setCacheHeaders(Environment environment, String urlPattern, int seconds) {
FilterRegistration.Dynamic filter = environment.servlets().addFilter(
"cacheControlFilter",
new Filter() {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
String[] cacheFileTypes = {"js","css","png","jpg","gif","svg"};
String filetypeRequested = FilenameUtils.getExtension(httpServletRequest.getRequestURL().toString());
if (httpServletRequest.getMethod() == "GET" && seconds > 0 && Arrays.asList(cacheFileTypes).contains(filetypeRequested)) {
httpServletResponse.setHeader("Cache-Control", "public, max-age=" + seconds);
Calendar c = Calendar.getInstance();
c.setTime(new Date());
c.add(Calendar.SECOND, seconds);
SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss zzz", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("GMT"));
httpServletResponse.setHeader("Expires", format.format(c.getTime()));
} else {
httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
httpServletResponse.setHeader("Expires", "0");
httpServletResponse.setHeader("Pragma", "no-cache");
}
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
);
filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, urlPattern);
}
PS:我无法获得接受答案的方式来设置 Expires-header 工作:
resp.setHeader("Expires", new Date().getTime()+500000 + "");
相比之下,我的非常臃肿,但它确实有效:
Calendar c = Calendar.getInstance();
c.setTime(new Date());
c.add(Calendar.SECOND, seconds);
SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss zzz", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("GMT"));
httpServletResponse.setHeader("Expires", format.format(c.getTime()));
【讨论】:
如果您只想为每个请求清除缓存,下面是我的解决方案,它使用 DropWizard 提供的 CacheBustingFilter。
定义一个自定义配置,在我的例子中是它的 WebConfiguration。在设置 DropWizard 应用程序时使用此配置。
public class WebConfiguration extends Configuration {
@JsonProperty
private String enableCacheControl;
public String getEnableCacheControl() {
return enableCacheControl;
}
public void setEnableCacheControl(String enableCacheControl) {
this.enableCacheControl = enableCacheControl;
}
}
获取您在 #1 中定义的配置,并根据其值注册 CacheBustingFilter。
在你的运行方法中添加这个 -
// get the cache control settings from the YAML - configuration
String enableCacheControl = configuration.getEnableCacheControl();
boolean enableCacheBustingFilter = Boolean.parseBoolean(enableCacheControl);
if(enableCacheBustingFilter){
// caching was enabled in YAML - was set to true - enabling the cacheBustingFilter
// this will ALWAYS return "must-revalidate,no-cache,no-store" in the Cache-Control response header
environment.servlets().addFilter("CacheBustingFilter", new CacheBustingFilter())
.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
}
【讨论】:
在较新版本的 Dropwizard @CacheControl 注释中。
https://dropwizardio.readthedocs.io/en/v0.7.0/manual/core.html#caching
【讨论】: