Cache-overskrifter i Spring MVC

1. Oversikt

I denne opplæringen lærer vi om HTTP-hurtigbufring. Vi vil også se på forskjellige måter å implementere denne mekanismen mellom en klient og en Spring MVC-applikasjon.

2. Introduksjon av HTTP-hurtigbufring

Når vi åpner en webside i en nettleser, laster den vanligvis ned mange ressurser fra webserveren:

For eksempel, i dette eksemplet, må en nettleser laste ned tre ressurser for en /Logg Inn side. Det er vanlig for en nettleser å komme med flere HTTP-forespørsler for hver webside. Nå, hvis vi ber om slike sider veldig ofte, forårsaker det mye nettverkstrafikk og det tar lengre tid å betjene disse sidene.

For å redusere nettverksbelastningen tillater HTTP-protokollen nettlesere å cache noen av disse ressursene. Hvis aktivert, kan nettlesere lagre en kopi av en ressurs i den lokale hurtigbufferen. Som et resultat kan nettlesere vise disse sidene fra den lokale lagringen i stedet for å be om det via nettverket:

En webserver kan lede nettleseren til å cache en bestemt ressurs ved å legge til en Cache-kontroll topptekst i svaret.

Siden ressursene er bufret som en lokal kopi,det er en risiko for å servere foreldet innhold fra nettleseren. Derfor legger webservere vanligvis til en utløpstid i Cache-kontroll Overskrift.

I de følgende avsnittene legger vi til denne overskriften i et svar fra Spring MVC-kontrolleren. Senere ser vi også Spring API-er for å validere de hurtigbufrede ressursene basert på utløpstiden.

3. Cache-kontroll i kontrollerens svar

3.1. Ved hjelp av ResponseEntity

Den enkleste måten å gjøre dette på er åbruke CacheControl byggherreklasse levert av Spring:

@GetMapping ("/ hallo / {name}") @ResponseBody public ResponseEntity hallo (@PathVariable String name) {CacheControl cacheControl = CacheControl.maxAge (60, TimeUnit.SECONDS) .noTransform () .mustRevalidate (); returner ResponseEntity.ok () .cacheControl (cacheControl) .body ("Hei" + navn); }

Dette vil legge til en Cache-kontroll topptekst i svaret:

@Test ugyldig nårHome_thenReturnCacheHeader () kaster unntak {this.mockMvc.perform (MockMvcRequestBuilders.get ("/ hallo / baeldung")) .andDo (MockMvcResultHandlers.print ()). Og Expect (MockMvcusultMatchers) .stat.). andExpect (MockMvcResultMatchers.header () .string ("Cache-Control", "max-age = 60, must-revalidate, no-transform")); }

3.2. Ved hjelp av HttpServletResponse

Ofte må kontrollerne returnere visningsnavnet fra behandlermetoden. Imidlertid, denResponseEntity klasse tillater oss ikke å returnere visningsnavnet og håndtere forespørselsorganet samtidig.

Alternativt, for slike kontrollere kan vi stille inn Cache-kontroll topptekst i HttpServletResponse direkte:

@GetMapping (value = "/ home / {name}") offentlig String home (@PathVariable String name, final HttpServletResponse response) {response.addHeader ("Cache-Control", "max-age = 60, must-revalidate, no -forvandle"); vende hjem"; }

Dette vil også legge til en Cache-kontroll topptekst i HTTP-svar som ligner på den siste delen:

@Test ugyldig nårHome_thenReturnCacheHeader () kaster unntak {this.mockMvc.perform (MockMvcRequestBuilders.get ("/ home / baeldung")). AndDo (MockMvcResultHandlers.print ()). AndExpect (MockMvcResultMatchers .stat. andExpect (MockMvcResultMatchers.header () .string ("Cache-Control", "max-age = 60, must-revalidate, no-transform")). og Expect (MockMvcResultMatchers.view (). navn ("hjem")); }

4. Cache-kontroll for statiske ressurser

Vårt MVC-program serverer generelt mange statiske ressurser som HTML-, CSS- og JS-filer. Siden slike filer bruker mye nettverksbåndbredde, er det derfor viktig for nettlesere å cache dem. Vi vil igjen aktivere dette med Cache-kontroll topptekst i svaret.

Våren lar oss kontrollere denne cacheoppførselen ved ressurskartlegging:

@Override public void addResourceHandlers (final ResourceHandlerRegistry registry) {registry.addResourceHandler ("/ resources / **"). AddResourceLocations ("/ resources /") .setCacheControl (CacheControl.maxAge (60, TimeUnit.SECONDS) .noTransform (). mustRevalidate ()); }

Dette sikrer at alle ressurserdefinert under/ ressurser blir returnert med en Cache-kontroll topptekst i svaret.

5. Cache-kontroll i Interceptors

Vi kan bruke avlyttere i vår MVC-applikasjon til å gjøre noe for- og etterbehandling for hver forespørsel. Dette er en annen plassholder der vi kan kontrollere caching-oppførselen til applikasjonen.

Nå, i stedet for å implementere en tilpasset interceptor, bruker vi WebContentInterceptor levert av Spring:

@Override public void addInterceptors (InterceptorRegistry registry) {WebContentInterceptor interceptor = new WebContentInterceptor (); interceptor.addCacheMapping (CacheControl.maxAge (60, TimeUnit.SECONDS) .noTransform () .mustRevalidate (), "/ login / *"); registry.addInterceptor (interceptor); }

Her registrerte vi WebContentInterceptor og la til Cache-kontroll topptekst som ligner på de siste avsnittene. Spesielt kan vi legge til forskjellige Cache-kontroll overskrifter for forskjellige URL-mønstre.

I eksemplet ovenfor, for alle forespørsler som begynner med /Logg Inn, vi legger til denne overskriften:

@Test ugyldig nårInterceptor_thenReturnCacheHeader () kaster unntak {this.mockMvc.perform (MockMvcRequestBuilders.get ("/ login / baeldung")) .andDo (MockMvcResultHandlers.print ()). Og Expect (MockMvcusresultat.). ()). andExpect (MockMvcResultMatchers.header () .string ("Cache-Control", "max-age = 60, must-revalidate, no-transform")); }

6. Validering av hurtigbuffer i vår-MVC

Så langt har vi diskutert forskjellige måter å inkludere a Cache-kontroll topptekst i svaret. Dette indikerer at klienter eller nettlesere skal cache ressursene basert på konfigurasjonsegenskaper som maks alder.

Det er generelt en god ide å legge til en cache-utløpstid for hver ressurs. Som et resultat kan nettlesere unngå å levere utløpte ressurser fra hurtigbufferen.

Selv om nettlesere alltid bør se etter utløp, er det ikke nødvendig å hente ressursen hver gang. Hvis en nettleser kan validere at en ressurs ikke har endret seg på serveren, kan den fortsette å servere den hurtigbufrede versjonen av den. Og for dette formålet gir HTTP oss to svaroverskrifter:

  1. Etag - en HTTP-svarhode som lagrer en unik hash-verdi for å bestemme om en hurtigbufret ressurs er endret på serveren - en tilsvarende Hvis-ingen-kamp forespørselstittel må ha den siste Etag-verdien
  2. Sist endret - et HTTP-svarhode som lagrer en tidsenhet da ressursen sist ble oppdatert - en tilsvarende Hvis-umodifisert-siden forespørselstittel må inneholde den sist endrede datoen

Vi kan bruke en av disse overskriftene for å sjekke om en utløpt ressurs må hentes på nytt. Etter å ha validert topptekstene,serveren kan enten sende ressursen på nytt eller sende en 304 HTTP-kode for å bety ingen endring. For sistnevnte scenario kan nettlesere fortsette å bruke hurtigbufrede ressurser.

De Sist endret topptekst kan bare lagre tidsintervaller med opptil sekunder presisjon. Dette kan være en begrensning i tilfeller der det kreves kortere utløp. Av denne grunn anbefales det å bruke Etag i stedet. Siden Etag header lagrer en hash-verdi, er det mulig å lage en unik hash opptil mer finere intervaller som nanosekunder.

Når det er sagt, la oss sjekke hvordan det ser ut til å bruke Sist endret.

Spring gir noen verktøy for å sjekke om forespørselen inneholder en utløpshode eller ikke:

@GetMapping (value = "/ productInfo / {name}") public ResponseEntity validate (@PathVariable String name, WebRequest request) {ZoneId zoneId = ZoneId.of ("GMT"); long lastModifiedTimestamp = LocalDateTime.of (2020, 02, 4, 19, 57, 45) .atZone (zoneId) .toInstant (). toEpochMilli (); if (request.checkNotModified (lastModifiedTimestamp)) {return ResponseEntity.status (304) .build (); } returner ResponseEntity.ok (). body ("Hei" + navn); }

Våren gir checkNotModified () metode for å sjekke om en ressurs er endret siden forrige forespørsel:

@Test ugyldig nårValidate_thenReturnCacheHeader () kaster unntak {HttpHeaders headers = new HttpHeaders (); headers.add (IF_UNMODIFIED_SINCE, "Tirsdag, 04. feb 2020 19:57:25 GMT"); this.mockMvc.perform (MockMvcRequestBuilders.get ("/ productInfo / baeldung"). headers (headers)) .andDo (MockMvcResultHandlers.print ()) .andExpect (MockMvcResultMatchers.status (). is (304)); }

7. Konklusjon

I denne artikkelen lærte vi om HTTP-hurtigbufring ved å bruke Cache-kontroll svartekst i Spring MVC. Vi kan enten legge til overskriften i kontrollerens svar ved å bruke ResponseEntity klasse eller gjennom ressurskartlegging for statiske ressurser.

Vi kan også legge til denne overskriften for bestemte URL-mønstre ved hjelp av Spring interceptors.

Som alltid er koden tilgjengelig på GitHub.