【问题标题】:Set cache control headers of static assets in Dropwizard在 Dropwizard 中设置静态资产的缓存控制标头
【发布时间】:2013-11-18 16:20:04
【问题描述】:

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

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

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

但是,经过进一步调查,com.yammer.dropwizard.bundles 包似乎从 5.1 版开始就不再是 Dropwizard 的一部分了。

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

【问题讨论】:

    标签: cache-control dropwizard


    【解决方案1】:

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

    我在与我的服务类相同的包中创建了一个 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, "/*") 
    

    【讨论】:

    • 这对我有帮助,谢谢。但应该注意的是,这个过滤器,如编写(和安装)的那样,适用于各种类型的所有请求(GET、PUT 等)。它不仅适用于静态资产的服务。
    • 从 1.0.6 开始工作。只需注册 env.servlets().addFilter("MyFilter", CacheControlFilter()).addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*")
    【解决方案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()));
    

    【讨论】:

    • 根据@Rich 对我的回答的评论,看起来我建议的内容可能不再适用于当前版本的 Dropwizard。自 2014 年以来我没有使用过它(或者实际上是 Java),所以我无法验证。
    【解决方案3】:

    如果您只想为每个请求清除缓存,下面是我的解决方案,它使用 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, "/*");
        }
    

    【讨论】:

    • 谢谢——这行得通!我错过了“addMappingForUrlPatterns”,没有它,它什么都不做:-(
    【解决方案4】:

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

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

    【讨论】:

      猜你喜欢
      • 2017-10-19
      • 1970-01-01
      • 2017-06-15
      • 2022-01-26
      • 1970-01-01
      • 2015-08-19
      • 2010-10-26
      • 2018-06-19
      • 1970-01-01
      相关资源
      最近更新 更多