Spring MVCでのhttp Caching
3502 ワード
Spring MVCでのhttp Caching
CacheはHTTPプロトコルにおける非常に重要な機能であり、Cacheを使用することでアプリケーションの性能を大幅に向上させ、データのネットワーク伝送を低減することができる.
通常、画像、CSS、JSファイルなどの静的リソースをキャッシュします.同様に、HTTP CacheとSpring MVCを組み合わせてダイナミックリソースのキャッシュを行うことができます.
では、ダイナミックリソースのキャッシュはいつ使用されますか?
このリソースが頻繁に更新されていない場合や、そのリソースがいつ更新されるかを正確に知っている場合にのみHTTP Cacheを使用することができます.
HTTP Cacheはリクエストヘッダによって実現され,主に3つの方式がある:期限切れ時間,最終更新時間,Etag.
有効期限はクライアント認証であり、最終更新時間とEtagはサーバ側認証である.
有効期限
期限切れにはCache-ControlとExpiresヘッダの2つの方法があります.
Cache-Controlでは、maxAgeを設定できます.この時間を超えると、リソースが再要求されます.次のようになります.
HeadでExpiresプロパティを設定することもできます.Expiresの時間は、次のような標準的な時間フォーマットが必要です.
Javaで使用する場合は、次の例を参照してください.
Cache-ControlとExpiresが同時に表示される場合は、Cache-Controlが優先されます.
Last-Modified
その検証ロジックは、クライアントが前回要求したLast-Modifiedに基づいてIf-Modified-Sinceを設定し、サーバ側がこのプロパティを受信した後、前のものと比較することができ、同じ場合は空のbodyを返すことができる.次のようになります.
ETag
Last-Modifiedの時間は秒までしか正確ではありませんが、もっと細粒度が必要ならETagが必要です.
ETagは、現在の時点であるリソースの唯一のタグと見なすことができ、そのリソースのhash値をETagとして取得することができます.
次のような実装があります.
Spring ETag filter
SpringはShallowEtagHeaderFilterを提供し、返された内容に基づいて自動的にEtagを生成します.
ETag計算は性能に影響を与える可能性があることに注意してください.
チュートリアルの詳細については、flydeanのブログを参照してください.
CacheはHTTPプロトコルにおける非常に重要な機能であり、Cacheを使用することでアプリケーションの性能を大幅に向上させ、データのネットワーク伝送を低減することができる.
通常、画像、CSS、JSファイルなどの静的リソースをキャッシュします.同様に、HTTP CacheとSpring MVCを組み合わせてダイナミックリソースのキャッシュを行うことができます.
では、ダイナミックリソースのキャッシュはいつ使用されますか?
このリソースが頻繁に更新されていない場合や、そのリソースがいつ更新されるかを正確に知っている場合にのみHTTP Cacheを使用することができます.
HTTP Cacheはリクエストヘッダによって実現され,主に3つの方式がある:期限切れ時間,最終更新時間,Etag.
有効期限はクライアント認証であり、最終更新時間とEtagはサーバ側認証である.
有効期限
期限切れにはCache-ControlとExpiresヘッダの2つの方法があります.
Cache-Controlでは、maxAgeを設定できます.この時間を超えると、リソースが再要求されます.次のようになります.
@GetMapping("/{id}")
ResponseEntity getProduct(@PathVariable long id) {
// …
CacheControl cacheControl = CacheControl.maxAge(30, TimeUnit.MINUTES);
return ResponseEntity.ok()
.cacheControl(cacheControl)
.body(product);
}
HeadでExpiresプロパティを設定することもできます.Expiresの時間は、次のような標準的な時間フォーマットが必要です.
Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
Javaで使用する場合は、次の例を参照してください.
@GetMapping("/forecast")
ResponseEntity getTodaysForecast() {
// ...
ZonedDateTime expiresDate = ZonedDateTime.now().with(LocalTime.MAX);
String expires = expiresDate.format(DateTimeFormatter.RFC_1123_DATE_TIME);
return ResponseEntity.ok()
.header(HttpHeaders.EXPIRES, expires)
.body(weatherForecast);
}
Cache-ControlとExpiresが同時に表示される場合は、Cache-Controlが優先されます.
Last-Modified
その検証ロジックは、クライアントが前回要求したLast-Modifiedに基づいてIf-Modified-Sinceを設定し、サーバ側がこのプロパティを受信した後、前のものと比較することができ、同じ場合は空のbodyを返すことができる.次のようになります.
@GetMapping("/{id}")
ResponseEntity getProduct(@PathVariable long id, WebRequest request) {
Product product = repository.find(id);
long modificationDate = product.getModificationDate()
.toInstant().toEpochMilli();
if (request.checkNotModified(modificationDate)) {
return null;
}
return ResponseEntity.ok()
.lastModified(modificationDate)
.body(product);
}
ETag
Last-Modifiedの時間は秒までしか正確ではありませんが、もっと細粒度が必要ならETagが必要です.
ETagは、現在の時点であるリソースの唯一のタグと見なすことができ、そのリソースのhash値をETagとして取得することができます.
次のような実装があります.
@GetMapping("/{id}")
ResponseEntity getProduct(@PathVariable long id, WebRequest request) {
Product product = repository.find(id);
String modificationDate = product.getModificationDate().toString();
String eTag = DigestUtils.md5DigestAsHex(modificationDate.getBytes());
if (request.checkNotModified(eTag)) {
return null;
}
return ResponseEntity.ok()
.eTag(eTag)
.body(product);
}
Spring ETag filter
SpringはShallowEtagHeaderFilterを提供し、返された内容に基づいて自動的にEtagを生成します.
@Bean
public FilterRegistrationBean filterRegistrationBean () {
ShallowEtagHeaderFilter eTagFilter = new ShallowEtagHeaderFilter();
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(eTagFilter);
registration.addUrlPatterns("/*");
return registration;
}
ETag計算は性能に影響を与える可能性があることに注意してください.
チュートリアルの詳細については、flydeanのブログを参照してください.