Spring MVC 如何在Sping Boot 中启用HTTP响应缓存

x9ybnkn6  于 2023-03-08  发布在  Spring
关注(0)|答案(9)|浏览(126)

我已经使用 Boot 实现了一个REST服务器,但是在阻止Spring设置禁用HTTP缓存的HTTP头时遇到了问题。
我的控制器如下:

@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);
    }
}

所有HTTP响应都包含以下标头:

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Expires: 0
Pragma: no-cache

我尝试了以下方法来删除或更改这些标题:
1.在控制器中调用setCacheSeconds(-1)
1.在控制器中调用httpResponse.setHeader("Cache-Control", "max-age=123")
1.定义@Bean,它返回我调用了setCacheSeconds(-1)WebContentInterceptor
1.将属性spring.resources.cache-period设置为-1或application.properties中的正值。
以上都没有任何效果。我如何在Sping Boot 中禁用或更改所有或个别请求的这些标头?

ztyzrc3y

ztyzrc3y1#

@Configuration
@EnableAutoConfiguration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/resources/")
                .setCachePeriod(31556926);

    }
}
igetnqfo

igetnqfo2#

如果您不想对静态资源进行身份验证,可以执行以下操作:

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());
    }
...
}

在您的application.properties中:

spring.resources.cache.cachecontrol.max-age=43200

有关ResourceProperties.java可以设置的更多属性,请访问www.example.com。

qc6wkl3g

qc6wkl3g3#

我在控制器中使用了下面的行。

ResponseEntity.ok().cacheControl(CacheControl.maxAge(secondWeWantTobeCached, TimeUnit.SECONDS)).body(objToReturnInResponse);

请注意,响应的头Cache-Control值为secondWeWantTobeCached。但是,如果我们在地址栏中输入url并按Enter键,请求将始终从Chrome发送到服务器。但是,如果我们从某个链接中点击url,浏览器将不会发送新的请求,它将从缓存中取出。

huus2vyu

huus2vyu4#

原来no-cache HTTP头是由Spring Security设置的,这在www.example.com中讨论http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#headers。
以下代码禁用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();
    }
}

我最终完全禁用了Spring Security的公共静态资源,如下所示(在上面的同一个类中):

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/static/public/**");
}

这需要配置两个资源处理程序来正确获取缓存控制标头:

@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);
    }
}

另请参见Serving static web resources in Spring Boot & Spring Security application

wtlkbnrh

wtlkbnrh5#

在spring Boot 中有很多方法可以缓存http,使用spring boot 2.1.1和spring security 5.1.1。

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

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

registry.addResourceHandler

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

.addResourceLocations

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

.setCacheControl

用于设置该高速缓存标头(无需解释)。
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.对于使用应用程序属性配置文件的资源

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

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.在主计长一级

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

no-cache, must-revalidate, private

getHeaderValue该高速缓存选项输出为字符串。例如

response.setHeader(HttpHeaders.CACHE_CONTROL,
            CacheControl.noCache()
                    .cachePrivate()
                    .mustRevalidate()
                    .getHeaderValue());
gpnt7bae

gpnt7bae6#

我发现这个Spring扩展:https://github.com/foo4u/spring-mvc-cache-control.
你只需要做三个步骤。
步骤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>

第2步(网络视图配置. java):

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CacheControlHandlerInterceptor());
    }
}

步骤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);
    }
}
tct7dpnv

tct7dpnv7#

可以通过以下方式覆盖特定方法的默认缓存行为:

@Controller
public class MyRestController {
    @RequestMapping(value = "/someUrl", method = RequestMethod.GET)
    public @ResponseBody ResponseEntity<String> myMethod(
            HttpServletResponse httpResponse) throws SQLException {
        return ResponseEntity.ok().cacheControl(CacheControl.maxAge(100, TimeUnit.SECONDS)).body(T)
    }
}
tsm1rwdh

tsm1rwdh8#

  • CacheControl* 类是一个流畅的构建器,它使我们能够轻松创建不同类型的缓存:
@GetMapping("/users/{name}")
public ResponseEntity<UserDto> getUser(@PathVariable String name) { 
    return ResponseEntity.ok()
      .cacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS))
      .body(new UserDto(name));
}

让我们在测试中达到这个端点,并Assert我们已经更改了标头:

given()
  .when()
  .get(getBaseUrl() + "/users/Michael")
  .then()
  .header("Cache-Control", "max-age=60");
dgjrabp2

dgjrabp29#

我遇到了类似的问题。我想得到一些动态资源(图片)缓存在浏览器中。如果图片改变(不是很频繁),我改变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
            }       
        }
    });

相关问题