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:
- 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
- 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.