如何在Spring Boot中将Cache-Control标头添加到静态资源?

问题描述 投票:22回答:6

如何在Spring Boot中为静态资源添加Cache-Control HTTP头?

尝试在应用程序中使用过滤器组件,它正确地写入标头,但Cache-Control标头被覆盖。

@Component
public class CacheBustingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) 
                                              throws IOException, ServletException {

        HttpServletResponse httpResp = (HttpServletResponse) resp;
        httpResp.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        httpResp.setHeader("This-Header-Is-Set", "no-cache, no-store, must-revalidate");
        httpResp.setHeader("Expires", "0");

        chain.doFilter(req, resp);
    }

我在浏览器中得到的是:

Cache-Control:no-store
This-Header-Is-Set:no-cache, no-store, must-revalidate
Expires:0

我想要的是:

Cache-Control:no-cache, no-store, must-revalidate
This-Header-Is-Set:no-cache, no-store, must-revalidate
Expires:0
java spring-boot cache-control
6个回答
13
投票

这是因为Spring Security:它会重写所有缓存标头以完全禁用缓存。 所以我们需要做两件事:

  1. 禁用静态资源的spring安全性
  2. 启用静态资源缓存处理

在当前版本的Spring Boot中,我们可以在application.properties config中更改此行为。

禁用某些资源的spring security:

# Comma-separated list of paths to exclude from the default secured 
security.ignored=/myAssets/**

启用为静态资源发送缓存标头:

# 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和其他)并重写您的appcache。

此外,如果有理由不对某些资源使用基于内容的版本 - 您可以使用备用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= 

在文档中查看更多内容


12
投票

根据ResourceHandlerRegistry文档 。 这很容易。 (我现在没有相关的代码。)

在配置静态资源的地方只需添加addResourceHandler方法,它将返回ResourceHandlerRegistration对象。

在那里你可以使用setCacheControl方法。 您需要做的是配置和设置CacheControl对象。

这是自4.2春季以来 ,否则你必须像下面这样做。

@Configuration
@EnableWebMvc
@ComponentScan("my.packages.here")
public class WebConfig extends WebMvcConfigurerAdapter {


   @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").setCachePeriod(0);
    }

}

3
投票

是控制资源的默认缓存标头的属性:

spring.resources.cache.cachecontrol.max-age: 3600

https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html


2
投票

spring boot中有很多方法可以缓存http资源。 使用弹簧靴2.1.1和弹簧安全5.1.1。

1.对于在代码中使用resourcehandler的资源(UNTESTED):

您可以通过这种方式添加自定义的资源扩展。

registry.addResourceHandler

用于添加uri路径以获取资源

.addResourceLocations

用于设置资源所在的文件系统中的位置(给定的是具有类路径的相对,但也可以是带文件:: //的绝对路径。)

.setCacheControl

用于设置缓存标头(自解释)。

资源链和解析器是可选的(在这种情况下与默认值完全相同)。

@Configuration
public class CustomWebMVCConfig implements WebMvcConfigurer {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**")
            .addResourceLocations("classpath:/static/")
            .setCacheControl(CacheControl.noStore()
                    .mustRevalidate())
            .setCacheControl(CacheControl.noCache())
            .resourceChain(true)
            .addResolver(new PathResourceResolver());
    }
}

2.使用应用程序属性配置文件的资源

与上面相同,减去特定模式,但现在作为配置。 此配置适用于列出的静态位置中的所有资源。

spring.resources.cache.cachecontrol.no-store=true
spring.resources.cache.cachecontrol.must-revalidate=true
spring.resources.cache.cachecontrol.no-cache=true

3.在控制器级别

这里的响应是在控制器方法中作为参数注入的HttpServletResponse。

response.setHeader(HttpHeaders.CACHE_CONTROL,
            "no-cache, must-revalidate, no-store");
response.setHeader("Expires", "0");

1
投票

Maleenc的,答案是对的。 但是,此实现存在一个问题。

以下代码将在第一个请求中提供正确的缓存控制头,但返回304(未修改)的未来请求将返回由spring security设置的默认缓存控制头。 {码}

public void addResourceHandlers(ResourceHandlerRegistry registry) {         
    registry.addResourceHandler("/resources/**").setCacheControl(CacheControl.maxAge(10, TimeUnit.SECONDS));
}

我已将此问题提交给春季团队,请访问https://jira.spring.io/browse/SPR-15133 。 这里有响应:“现在你不应该为你的整个应用程序禁用安全缓存控制头;在该问题注释中解释了为特定路径(资源处理,这里)禁用那些头的正确方法,请参阅”解决方法“ 部分。”


1
投票

使用springen 1.3.3,我使用maleenc回答得到了404回答。 我可以通过添加资源位置来纠正它:

@Configuration
public class HttpClientConfiguration extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").setCacheControl(CacheControl.maxAge(1, TimeUnit.DAYS))
                .addResourceLocations("/");
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.