Java 如何在 Spring Boot 中启用 HTTP 响应缓存
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24164014/
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
How to enable HTTP response caching in Spring Boot
提问by Samuli Pahaoja
I have implemented a REST server using Spring Boot 1.0.2. I'm having trouble preventing Spring from setting HTTP headers that disable HTTP caching.
我已经使用 Spring Boot 1.0.2 实现了一个 REST 服务器。我无法阻止 Spring 设置禁用 HTTP 缓存的 HTTP 标头。
My controller is as following:
我的控制器如下:
@Controller
public class MyRestController {
@RequestMapping(value = "/someUrl", method = RequestMethod.GET)
public @ResponseBody ResponseEntity<String> myMethod(
HttpServletResponse httpResponse) throws SQLException {
return new ResponseEntity<String>("{}", HttpStatus.OK);
}
}
All HTTP responses contain the following headers:
所有 HTTP 响应都包含以下标头:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Expires: 0
Pragma: no-cache
I've tried the following to remove or change those headers:
我尝试了以下方法来删除或更改这些标题:
- Call
setCacheSeconds(-1)
in the controller. - Call
httpResponse.setHeader("Cache-Control", "max-age=123")
in the controller. - Define
@Bean
that returnsWebContentInterceptor
for which I've calledsetCacheSeconds(-1)
. - Set property
spring.resources.cache-period
to -1 or a positive value inapplication.properties
.
- 调用
setCacheSeconds(-1)
控制器。 - 调用
httpResponse.setHeader("Cache-Control", "max-age=123")
控制器。 - 定义我调用的
@Bean
返回值。WebContentInterceptor
setCacheSeconds(-1)
- 将属性设置
spring.resources.cache-period
为 -1 或 中的正值application.properties
。
None of the above have had any effect. How do I disable or change these headers for all or individual requests in Spring Boot?
以上都没有任何影响。如何在 Spring Boot 中为所有或单个请求禁用或更改这些标头?
采纳答案by Samuli Pahaoja
Turns out the no-cache HTTP headers are set by Spring Security. This is discussed in http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#headers.
结果证明无缓存 HTTP 标头是由 Spring Security 设置的。这在http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#headers 中进行了讨论。
The following disables the HTTP response header Pragma: no-cache
, but doesn't otherwise solve the problem:
以下禁用 HTTP 响应标头Pragma: no-cache
,但不能解决问题:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// Prevent the HTTP response header of "Pragma: no-cache".
http.headers().cacheControl().disable();
}
}
I ended up disabling Spring Security completely for public static resources as following (in the same class as above):
我最终为公共静态资源完全禁用了 Spring Security,如下所示(在与上面相同的类中):
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/static/public/**");
}
This requires configuring two resource handlers to get cache control headers right:
这需要配置两个资源处理程序以正确获取缓存控制标头:
@Configuration
public class MvcConfigurer extends WebMvcConfigurerAdapter
implements EmbeddedServletContainerCustomizer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// Resources without Spring Security. No cache control response headers.
registry.addResourceHandler("/static/public/**")
.addResourceLocations("classpath:/static/public/");
// Resources controlled by Spring Security, which
// adds "Cache-Control: must-revalidate".
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.setCachePeriod(3600*24);
}
}
See also Serving static web resources in Spring Boot & Spring Security application.
回答by Michal Ambro?
I run into similar problem. I wanted to get just some of dynamic resources (images) cached in the browser. If image changes (not very often) I change the part of uri... This is my sollution
我遇到了类似的问题。我只想在浏览器中缓存一些动态资源(图像)。如果图像更改(不经常),我会更改 uri 的部分...这是我的解决方案
http.headers().cacheControl().disable();
http.headers().addHeaderWriter(new HeaderWriter() {
CacheControlHeadersWriter originalWriter = new CacheControlHeadersWriter();
@Override
public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
Collection<String> headerNames = response.getHeaderNames();
String requestUri = request.getRequestURI();
if(!requestUri.startsWith("/web/eventImage")) {
originalWriter.writeHeaders(request, response);
} else {
//write header here or do nothing if it was set in the code
}
}
});
回答by dap.tci
I have found this Spring extension: https://github.com/foo4u/spring-mvc-cache-control.
我找到了这个 Spring 扩展:https: //github.com/foo4u/spring-mvc-cache-control。
You just have to do three steps.
你只需要做三个步骤。
Step 1 (pom.xml):
第 1 步(pom.xml):
<dependency>
<groupId>net.rossillo.mvc.cache</groupId>
<artifactId>spring-mvc-cache-control</artifactId>
<version>1.1.1-RELEASE</version>
<scope>compile</scope>
</dependency>
Step 2 (WebMvcConfiguration.java):
第 2 步(WebMvcConfiguration.java):
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CacheControlHandlerInterceptor());
}
}
Step 3 (Controller):
第 3 步(控制器):
@Controller
public class MyRestController {
@CacheControl(maxAge=31556926)
@RequestMapping(value = "/someUrl", method = RequestMethod.GET)
public @ResponseBody ResponseEntity<String> myMethod(
HttpServletResponse httpResponse) throws SQLException {
return new ResponseEntity<String>("{}", HttpStatus.OK);
}
}
回答by Vazgen Torosyan
@Configuration
@EnableAutoConfiguration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/")
.setCachePeriod(31556926);
}
}
回答by cstroe
If you don't care to have your static resources authenticated, you could do this:
如果您不关心对静态资源进行身份验证,您可以这样做:
import static org.springframework.boot.autoconfigure.security.servlet.PathRequest.toStaticResources;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
@Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity
.ignoring()
.requestMatchers(toStaticResources().atCommonLocations());
}
...
}
and in your application.properties
:
并在您的application.properties
:
spring.resources.cache.cachecontrol.max-age=43200
See ResourceProperties.javafor more properties that can be set.
有关可以设置的更多属性,请参阅ResourceProperties.java。
回答by Merv
There are a lot of ways in spring boot for http caching. 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:
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("/*.js", "/*.css", "/*.ttf", "/*.woff", "/*.woff2", "/*.eot",
"/*.svg")
.addResourceLocations("classpath:/static/")
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS)
.cachePrivate()
.mustRevalidate())
.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.cache-private=true
spring.resources.cache.cachecontrol.must-revalidate=true
spring.resources.cache.cachecontrol.max-age=31536000
spring.resources.static-locations=classpath:/static/
3. At controller level
3. 在控制器层面
Response here is the HttpServletResponse injected in the controller method as parameter.
这里的Response是作为参数注入到控制器方法中的HttpServletResponse。
no-cache, must-revalidate, private
getHeaderValue will output the cache options as string. e.g.
getHeaderValue 将缓存选项输出为字符串。例如
response.setHeader(HttpHeaders.CACHE_CONTROL,
CacheControl.noCache()
.cachePrivate()
.mustRevalidate()
.getHeaderValue());
回答by Vikky
I used below lines in my controller.
我在控制器中使用了以下几行。
ResponseEntity.ok().cacheControl(CacheControl.maxAge(secondWeWantTobeCached, TimeUnit.SECONDS)).body(objToReturnInResponse);
Please note that Response will have header Cache-Control with value secondWeWantTobeCached. However if we are typing url in addressbar and pressing enter, Request will always be sent from Chrome to server. However if we hit url from some link, browser will not send a new request and it will be taken from cache.
请注意,响应将具有值为 secondWeWantTobeCached 的标头 Cache-Control。但是,如果我们在地址栏中输入 url 并按 Enter,请求将始终从 Chrome 发送到服务器。但是,如果我们从某个链接点击 url,浏览器将不会发送新请求,而是从缓存中获取。
回答by Nausheen Khan
Overriding of default caching behavior for a particular method can be done in the below way:
可以通过以下方式覆盖特定方法的默认缓存行为:
@Controller
public class MyRestController {
@RequestMapping(value = "/someUrl", method = RequestMethod.GET)
public @ResponseBody ResponseEntity<String> myMethod(
HttpServletResponse httpResponse) throws SQLException {
return new ResponseEntity.ok().cacheControl(CacheControl.maxAge(100, TimeUnit.SECONDS)).body(T)
}
}