Подтвердить что ты не робот

Как включить кеширование HTTP-ответов в Spring Загрузка

Я реализовал сервер REST с помощью Spring Boot 1.0.2. У меня возникли проблемы с предотвращением 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

Я попробовал следующее: удалить или изменить те заголовки:

  • Вызовите setCacheSeconds(-1) в контроллере.
  • Вызовите httpResponse.setHeader("Cache-Control", "max-age=123") в контроллере.
  • Определите @Bean, который возвращает WebContentInterceptor, для которого я назвал setCacheSeconds(-1).
  • Задайте свойство spring.resources.cache-period -1 или положительное значение в application.properties.

Ничто из перечисленного не имеет никакого эффекта. Как отключить или изменить эти заголовки для всех или отдельных запросов в Spring Загрузка?

4b9b3361

Ответ 1

Оказывается, HTTP-заголовки no-cache устанавливаются с помощью Spring Безопасность. Это обсуждается в 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 Безопасность для общедоступных статических ресурсов следующим образом (в том же классе, что и выше):

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

См. также Обслуживание статических веб-ресурсов в Spring Boot и Spring приложении безопасности.

Ответ 2

Я нашел это расширение 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 (WebMvcConfiguration.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);
    }
}

Ответ 3

В весенней загрузке есть много способов для http-кэширования. Использование пружинного башмака 2.1.1 и дополнительно пружинной безопасности 5.1.1.

1. Для ресурсов, использующих обработчик ресурсов в коде:

Таким способом вы можете добавлять индивидуальные расширения ресурсов.

registry.addResourceHandler

Для добавления пути URI, где получить ресурс

.addResourceLocations

Предназначен для установки местоположения в файловой системе, где расположены ресурсы (данное значение является относительным с classpath, но также возможен абсолютный путь с file :://.)

.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. На уровне контроллера

Ответом здесь является HttpServletResponse, введенный в метод контроллера в качестве параметра.

no-cache, must-revalidate, private

getHeaderValue выведет параметры кэша в виде строки. например

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

Ответ 4

Spring Безопасность отключает ваши заголовки кеширования. Если у вас есть динамические ответы, которые не нужно защищать, и вы хотите использовать заголовки http для их кеширования - просто путь к вашему application.property:

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

Подробнее в docs

Ответ 5

У меня возникает аналогичная проблема. Я хотел получить только некоторые из динамических ресурсов (изображений), кэшированных в браузере. Если изображение меняется (не очень часто), я меняю часть 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
            }       
        }
    });

Ответ 6

@Configuration
@EnableAutoConfiguration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

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

    }
}

Ответ 7

Если вам не нужна аутентификация ваших статических ресурсов, вы можете сделать это:

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 для дополнительных свойств, которые могут быть установлены.

Ответ 8

Я использовал следующие строки в моем контроллере.

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

Обратите внимание, что в Response будет заголовок Cache-Control со значением secondWeWantTobeCached. Однако если мы введем url в адресную строку и нажмем клавишу ввода, запрос всегда будет отправляться с Chrome на сервер. Однако, если мы нажмем на ссылку по какой-либо ссылке, браузер не отправит новый запрос, и он будет взят из кеша.