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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33214501/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:28:02  来源:igfitidea点击:

How to add Cache-Control header to static resource in Spring Boot?

javaspring-bootcache-control

提问by MatteKarla

How can I add Cache-ControlHTTP header in Spring Boot for static resources?

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

Tried using a filter-component in the application, which writes headers correctly, but Cache-Controlheader gets overwritten.

尝试在应用程序中使用过滤器组件,该组件正确写入标头,但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);
    }

What I get in the browser is:

我在浏览器中得到的是:

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

What I would like is:

我想要的是:

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

采纳答案by Maleen Abewardana

As per the documentation, of ResourceHandlerRegistry. It is pretty easy. (I have no code related to it right now.)

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

In the place where you configure your static resources just add addResourceHandlermethod, It will return ResourceHandlerRegistrationobject.

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

There you can use setCacheControlmethod. What you have to do is configure and set a CacheControlobejct.

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

This is since spring 4.2, else you will have to do it like below.

这是从 spring 4.2 开始的,否则你将不得不像下面那样做。

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


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

}

回答by Alexandr Latushkin

This happens because of Spring Security: it rewrites all cache headers to disable caching totally. So we need to do two things:

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

  1. Disable spring security for static resources
  2. Enable static resource cache processing
  1. 禁用静态资源的 spring 安全性
  2. 启用静态资源缓存处理

In current version of Spring Boot we can change this behavior in application.properties config.

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

Disable spring security for some resources:

禁用某些资源的 spring 安全性:

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

Enable sending cache headers for static resources:

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

# 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/

That's all. Now Spring will check if your static files was changed and can send smarter responses (If-Modiffied-Since and others) and rewrite your appcache also.

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

Also, if there are reasons to not use content-based version for some resources - you can use alternate FixedVersion strategy and set version explicitly in your config:

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

See more in docs

在文档中查看更多

回答by Thomas Jahncke

Maleenc's, answer is correct. However, there is one issue with this implementation.

马林克的,答案是正确的。但是,这种实现存在一个问题。

The following code will provide the correct cache-control header on the first request, but not a future request that returns 304 (Not-Modified) will return the default cache-control header set by spring security. {code}

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

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

I have raised up this issue to the spring team, see https://jira.spring.io/browse/SPR-15133. Here was there response: "Now you shouldn't disable security cache-control headers for your whole application indeed; the proper way to disable those for a specific path (resource handling, here) is explained in that issue comment, see the "Workaround" section."

我已经向 spring 团队提出了这个问题,请参阅https://jira.spring.io/browse/SPR-15133。这是那里的回应:“现在您确实不应该为整个应用程序禁用安全缓存控制标头;在该问题评论中解释了为特定路径(资源处理,此处)禁用这些标头的正确方法,请参阅“解决方法“ 部分。”

回答by Ronan Fauglas

Using spring boot 1.3.3, I had a 404 answer using maleenc answer. I could correct it by adding a resource location:

使用 spring boot 1.3.3,我有一个使用maleenc answer的404答案。我可以通过添加资源位置来纠正它:

@Configuration
public class HttpClientConfiguration extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").setCacheControl(CacheControl.maxAge(1, TimeUnit.DAYS))
                .addResourceLocations("/");
    }
}

回答by Mateusz Stefek

The are properties that control the default cache headers for resources:

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

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

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

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

回答by Merv

There are a lot of ways in spring boot for caching http resource. Using spring boot 2.1.1 and additionally spring security 5.1.1.

spring boot中缓存http资源的方法有很多。使用 spring boot 2.1.1 和额外的 spring security 5.1.1。

1. For resources using resourcehandler in code (UNTESTED):

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

You can add customized extensions of resources this way.

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

registry.addResourceHandler

Is for adding the uri path where to get the resource

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

.addResourceLocations

Is for setting the location in the filesystem where the resources are located( given is a relative with classpath but absolute path with file::// is also possible.)

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

.setCacheControl

Is for setting the cache headers (self explanatory.)

用于设置缓存头(不言自明。)

Resourcechain and resolver are optional (in this case exactly as the default values.)

Resourcechain 和 resolver 是可选的(在这种情况下与默认值完全相同。)

@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. For resources using application properties config file

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

Same as above, minus the specific patterns, but now as config. This configuration is applied to all resources in the static-locations listed.

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

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

3. At controller level

3. 在控制器层面

Response here is the HttpServletResponse injected in the controller method as parameter.

这里的Response是作为参数注入到控制器方法中的HttpServletResponse。

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