Dinamikus erőforrások cache-elése Spring MVC-vel
Az előző poszt
bemutatta, hogyan működik a HTTP protokoll szintű cache-elés, valamint
Spring MVC segítségével hogyan lehet olyan statikus erőforrásokat (pl.
CSS és JavaScript állományok) cache-elni. Ott szó esett az Etag
HTTP
fejlécről is, ez a poszt ennek használatát mutatja be dinamikus erőforrások
esetén.
Emlékeztetőül egy erőforrás lekérdezésekor annak verziójának egy
azonosítóját is küldjük a HTTP válasz Etag
fejlécében. Amennyiben a
böngésző nem automatikusan a cache-ből szolgálja ki az erőforrást,
megkérdezi a szervert, hogy történt-e ott módosítás. Ezt úgy teszi, hogy
elküldi a kapott verziószámot a HTTP kérés If-none-match
fejlécében.
Amennyiben a szerver azt látja, hogy az erőforrás nem változott, azaz az
aktuális és a küldött verziószám megegyezik, akkor egy 304 Not Modified
státuszt küld vissza a böngészőnek. Ekkor a böngésző a tartalmat a
cache-ből fogja kiszolgálni. Amennyiben az erőforrás változott, és a két
verziószám eltér, a szerver visszaküldi az erőforrás teljes tartalmát.
A GitHubon lévő példakód szemlélteti, hogy hogyan használhatjuk az ETaget Springes controller osztályból.
Az Etag beállítása a ResponseEntity
használatával történhet, ahogy a
következő példa is mutatja.
Itt az Etag értékét a hashToEtag
metódus az objektum hashkódja alapján
számolja. Amire vigyázni kell, hogy idézőjelek között kell szerepelnie.
A példában ez azért működik, mert bár az osztályok hashCode()
metódusát
ugyan nem írtam felül, de egy ConcurrentMap
alapú cache-ben eltároltam,
így nem kerülnek újra lepéldányosításra, ezért hashkódjuk megmarad.
Módosítás esetén a cache-be új példány kerül, így új hashkódja lesz.
Nézzük meg, hogy hogyan is működik. Teszteléshez a HTTPie eszközt használtam, mely hasonló, mint a curl, csak egyszerűbben használható, és a kimenete színezett, ezért könnyebben olvasható.
Először tehát lekérjük az alkalmazottak listáját (a lényegtelen sorokat töröltem).
vicziani@jtechlog:~$ http get localhost:8080/api/employees
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
ETag: "785565526"
[
{
"id": 1,
"name": "John Doe"
}
]
Látható, hogy egy elemű lista. Ha még egyszer lekérjük, immár a
If-none-match
fejléccel, 304 Not Modified
választ kapunk.
vicziani@jtechlog:~$ http get localhost:8080/api/employees 'If-none-match:"785565526"'
HTTP/1.1 304 Not Modified
ETag: "785565526"
Felveszünk egy új entitást.
vicziani@jtechlog:~$ http post localhost:8080/api/employees name='John Roe'
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
"id": 2,
"name": "John Roe"
}
Majd újra lekérjük az alkalmazottak listáját.
vicziani@jtechlog:~$ http get localhost:8080/api/employees 'If-none-match:"785565526"'
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
ETag: "-1478013167"
[
{
"id": 1,
"name": "John Doe"
},
{
"id": 2,
"name": "John Roe"
}
]
Láthatjuk, hogy most már 200 OK
státuszt kapunk, és az erőforrás újra
letöltésre kerül új Etaggel.
Ugyanez megfogalmazva a Spring MVC Test Frameworkkel a következőképp néz ki.