【问题标题】:how to selectively disable cache for spring boot (manifest.appcache)如何选择性地禁用 Spring Boot 的缓存(manifest.appcache)
【发布时间】:2014-11-30 17:49:52
【问题描述】:

question 可以看出,spring security 为 spring boot 管理缓存。从 spring boot documentation 它显示了如何使用以下方法为资源设置缓存:

spring.resources.cache-period= # cache timeouts in headers sent to browser

cache-period 非常适合 Spring Boot 的所有预定义静态位置(即/css**/js/**/images/**),但我还生成了一个manifest.appcache 用于离线下载我的静态资产和由于上述所有 spring security/boot 使用 manifest.appcache 发回缓存头

"method": "GET",
"path": "/manifest.appcache",
"response": {
    "X-Application-Context": "application:local,flyway,oracle,kerberos:8080",
    "Expires": "Tue, 06 Oct 2015 16:59:39 GMT",
    "Cache-Control": "max-age=31556926, must-revalidate",
    "status": "304"
}

我想知道如何为manifest.appcache 添加排除项。无论我的标头如何,IE 和 Chrome 似乎都对 appcache “做正确的事情”,但 FF 似乎在注意到 appcache 何时发生更改时更加奇特,我认为我的缓存标头搞砸了。

编辑: 我应该从WebMvcAutoConfiguration 的源代码中添加它,它显示了如何为资源设置缓存,我只是不确定如何为我的 1 个案例选择性地禁用,而不会破坏 Spring Boot 在此文件中设置的其余部分.

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        if (!this.resourceProperties.isAddMappings()) {
            logger.debug("Default resource handling disabled");
            return;
        }

        Integer cachePeriod = this.resourceProperties.getCachePeriod();
        if (!registry.hasMappingForPattern("/webjars/**")) {
            registry.addResourceHandler("/webjars/**")
                    .addResourceLocations("classpath:/META-INF/resources/webjars/")
                    .setCachePeriod(cachePeriod);
        }
        if (!registry.hasMappingForPattern("/**")) {
            registry.addResourceHandler("/**")
                    .addResourceLocations(RESOURCE_LOCATIONS)
                    .setCachePeriod(cachePeriod);
        }
    }

【问题讨论】:

  • 只需添加一个扩展 WebMvcConfigurerAdapter 的类并为该资源添加特定规则即可。
  • 我试过这个:@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { super.addResourceHandlers(registry); registry.addResourceHandler("/manifest.appcache").addResourceLocations("/").setCachePeriod(0); } 但我得到了 404。
  • 使用/ 将使它尝试从Web 应用程序的根目录检索。确保 / 覆盖文件的正确物理位置。
  • 我的 manifest.appcache 位于应用的根目录中(在本例中为 /public,与 index.html 所在的位置相同。
  • 那么应该是/public 而不是/

标签: spring-boot html5-appcache


【解决方案1】:

基于this answer详述IE需要“max-age=1, must-revalidate”,并通过在所有浏览器上测试,设置属性值为

spring.resources.cache-period=1

将允许写入正确的 http 标头,从而可以正确处理 appcache 清单。这不是我希望的解决方案(我想要的缓存周期为 0 和正确的标头是我想要的),但它确实使浏览器正常运行并正确利用 appcache 清单。

再次总结解决方案上下文 - 这是我的应用程序,它离线下载我的所有资产 (js/css/html) 并从 appcache 提供服务。

【讨论】:

    【解决方案2】:

    感谢 Q 和 A!

    我们遇到了类似的问题:除了一个 (FF) 之外的所有浏览器(Chrome、Safari、IE)都没有缓存清单文件,而是在更改后重新加载。

    但是,在 Spring Boot 中设置缓存周期设置并没有完全解决问题。此外,我不想为 Spring Boot 应用程序提供的所有文件设置缓存控制参数,而只想禁用清单的缓存。

    我的解决方案由两部分组成:

    1. 在清单文件中提供“rev”注释。尽管W3C spec 未涵盖某些浏览器,但似乎需要这样的注释来检测清单或引用(缓存)文件中的更改:

      # rev 7
      

      我们现在将缓存清单文件中的“rev”参数更改为 Maven 生成的唯一内部版本号:https://github.com/dukecon/dukecon_html5/commit/b60298f0b856a7e54c97620f278982142e3e1f45)。

    2. 通过提供一个过滤器禁用缓存,该过滤器将标题“Cache-Control: no-cache”添加到 cache.manifest 文件模式:https://github.com/dukecon/dukecon_server/commit/dc02f26996cb172df804da007546f439df75126d

    【讨论】:

    • 可靠的答案,谢谢。对于您的第一点,它不是 rev 正在改变任何东西,浏览器正在查看 cmets 并对其进行哈希处理。如果它检测到哈希值发生变化,它会使缓存无效并重新加载。对于您的第二点,这绝对是首选解决方案,因为它专门针对 appcache 并且不会干扰其他缓存周期。我会将您的答案标记为首选答案。
    【解决方案3】:

    在当前版本(2016 年 2 月)中,无需在代码中执行任何操作来更改默认行为。 只需在您的 application.properties 中进行一些配置:

    # Enable HTML5 application cache manifest rewriting.
    spring.resources.chain.html-application-cache=true
    
    # Enable the Spring Resource Handling chain. Disabled by default unless at least one strategy has been enabled.
    spring.resources.chain.enabled=true
    # Enable the content Version Strategy.
    spring.resources.chain.strategy.content.enabled=true 
    # Comma-separated list of patterns to apply to the Version Strategy.
    spring.resources.chain.strategy.content.paths=/** 
    
    # Locations of static resources.
    spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
    

    就是这样。现在 Spring 将检查您的静态文件是否已更改,并可以发送更智能的响应(If-Modiffied-Since 等)并重写您的应用缓存。

    此外,如果有理由不为某些资源使用基于内容的版本 - 您可以使用备用 FixedVersion 策略并在配置中明确设置版本:

    #Enable the fixed Version Strategy.
    spring.resources.chain.strategy.fixed.enabled=false 
    # Comma-separated list of patterns to apply to the Version Strategy.
    spring.resources.chain.strategy.fixed.paths= 
    # Version string to use for the Version Strategy.
    spring.resources.chain.strategy.fixed.version= 
    

    附:不要忘记 Spring Security:它会重写缓存标头并禁用缓存。

    docs中查看更多信息

    【讨论】:

    • 别忘了添加spring.resources.cache-period=3600 以秒为单位过期。
    • 在这里添加了答案。页面现在无法加载。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 2019-07-11
    • 2016-10-28
    • 2016-05-10
    • 2011-04-21
    相关资源
    最近更新 更多