it-swarm.com.de

So aktivieren Sie das HTTP-Antwort-Caching in Spring Boot

Ich habe einen REST -Server mit Spring Boot 1.0.2 implementiert. Ich habe Probleme, Spring zu verhindern, HTTP-Header festzulegen, die das HTTP-Caching deaktivieren.

Mein Controller ist wie folgt:

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

Alle HTTP-Antworten enthalten die folgenden Header:

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

Ich habe folgendes versucht, um diese Header zu entfernen oder zu ändern:

  1. Rufen Sie setCacheSeconds(-1) in der Steuerung auf.
  2. Rufen Sie httpResponse.setHeader("Cache-Control", "max-age=123") in der Steuerung auf.
  3. Definieren Sie @Bean, der WebContentInterceptor zurückgibt, für den ich setCacheSeconds(-1) aufgerufen habe.
  4. Setzen Sie die Eigenschaft spring.resources.cache-period auf -1 oder einen positiven Wert in application.properties.

Keines der obigen Punkte hatte irgendeine Wirkung. Wie kann ich diese Header für alle oder einzelne Anforderungen in Spring Boot deaktivieren oder ändern?

39

Es stellt sich heraus, dass die No-Cache-HTTP-Header von Spring Security festgelegt wurden. Dies wird in http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#headers diskutiert.

Der folgende Befehl deaktiviert den HTTP-Antwortheader Pragma: no-cache, löst das Problem jedoch sonst nicht:

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

Ich habe Spring Security für öffentliche statische Ressourcen wie folgt komplett deaktiviert (in derselben Klasse wie oben):

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

Dazu müssen Sie zwei Ressourcenhandler konfigurieren, um die Cache-Steuerungsheader richtig zu machen:

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

Siehe auch Statische Webressourcen in Spring Boot & Spring Security-Anwendung bereitstellen .

48

Ich habe diese Spring-Erweiterung gefunden: https://github.com/foo4u/spring-mvc-cache-control .

Sie müssen nur drei Schritte machen.

Schritt 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>

Schritt 2 (WebMvcConfiguration.Java):

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

Schritt 3 (Controller):

@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);
    }
}
4
dap.tci

Es gibt viele Möglichkeiten im Spring Boot für das HTTP-Caching. Federpaket 2.1.1 und zusätzlich Federsicherung verwenden 5.1.1.

1. Für Ressourcen, die Ressourcenhandler im Code verwenden:

Sie können auf diese Weise benutzerdefinierte Erweiterungen von Ressourcen hinzufügen.

registry.addResourceHandler

Zum Hinzufügen des URI-Pfads, an dem die Ressource abgerufen werden soll

.addResourceLocations

Dient zum Festlegen des Speicherorts im Dateisystem, an dem sich die Ressourcen befinden ( Ist ein relativer Klassenpfad, aber absoluter Pfad mit file :: // ist ebenfalls möglich.)

.setCacheControl

Dient zum Setzen der Cache-Header (selbsterklärend.)

Resourcechain und Resolver sind optional (in diesem Fall genau wie die Standardwerte.)

@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. Für Ressourcen, die Konfigurationsdateien für Anwendungseigenschaften verwenden

Wie oben, minus der spezifischen Muster, aber jetzt als config . Diese Konfiguration wird auf alle Ressourcen in den aufgelisteten statischen Speicherorten angewendet.

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. Auf Controller-Ebene

Die Antwort hier ist der HttpServletResponse, der als Parameter in die Controller-Methode eingefügt wurde.

no-cache, must-revalidate, private

getHeaderValue gibt die Cache-Optionen als String aus. z.B. 

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

Wenn Sie nicht möchten, dass Ihre statischen Ressourcen authentifiziert werden, können Sie Folgendes tun:

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

und in deinem application.properties:

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

Siehe ResourceProperties.Java für weitere Eigenschaften, die festgelegt werden können.

0
cstroe
@Configuration
@EnableAutoConfiguration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

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

    }
}
0
Vazgen Torosyan

Ich stoße auf ein ähnliches Problem. Ich wollte nur einige dynamische Ressourcen (Bilder) im Browser zwischengespeichert bekommen. Wenn sich das Bild ändert (nicht sehr oft), ändere ich den Teil von URI ... Dies ist meine Lösung

    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
            }       
        }
    });
0
Michal Ambrož

Ich habe in meinem Controller die folgenden Zeilen verwendet.

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

Bitte beachten Sie, dass Response eine Header-Cache-Steuerung mit dem Wert secondWeWantTobeCached hat. Wenn wir jedoch eine URL in die Adressleiste eingeben und die Eingabetaste drücken, wird die Anfrage immer vom Chrome zum Server gesendet. Wenn wir jedoch über einen Link auf die URL klicken, sendet der Browser keine neue Anfrage aus dem Cache genommen werden.

0
Vikky