7

在 Dropwizard 服务中设置静态资产的缓存控制标头的最佳方法是什么?

一些谷歌搜索显示了一个 AssetsBundle 构造函数:

AssetsBundle(String resourcePath, com.google.common.cache.CacheBuilderSpec cacheBuilderSpec, String uriPath)

然而,在进一步调查中,com.yammer.dropwizard.bundles 包似乎自 5.1 版以来就不再是 Dropwizard 的一部分。

也许我遗漏了一些明显的东西,但是有没有首选的方法来处理这个问题?

4

4 回答 4

10

如果有人感兴趣(从这个问题的浏览量来看,他们可能没有)这就是我解决这个问题的方法。

我在与我的服务类相同的包中创建了一个 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, "/*") 
于 2013-12-04T16:20:14.300 回答
2

基于 Tim Barclay 的回答,我创建了一个过滤器,如果请求的资源是扩展名为 js、css、png、jpg、gif 或 svg 的文件,则该过滤器设置Cache-ControlExpires未来一年。否则缓存被禁用。

希望它对某人有帮助!

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()));
于 2016-04-07T08:39:19.837 回答
2

如果您只想清除每个请求的缓存,下面是我的解决方案,它使用 DropWizard 提供的 CacheBustingFilter。

  1. 定义一个自定义配置,在我的例子中是它的 WebConfiguration。在设置 DropWizard 应用程序时使用此配置。

    public class WebConfiguration extends Configuration {
    
    @JsonProperty
    private String enableCacheControl;
    
    public String getEnableCacheControl() {
        return enableCacheControl;
    }
    
    public void setEnableCacheControl(String enableCacheControl) {
        this.enableCacheControl = enableCacheControl;
    }
    

    }

  2. 获取您在#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, "/*");
    }
于 2015-10-14T22:22:20.430 回答
0

在较新版本的 Dropwizard@CacheControl注释中。

https://dropwizardio.readthedocs.io/en/v0.7.0/manual/core.html#caching

于 2020-02-11T04:59:09.067 回答