概要
ハンドラーメソッド(コントローラークラスのメソッド)に付加したマーカーアノテーションを判別してResponse HeaderにCache-Controlをセットするサンプルコードです。
環境
- Windows10 Professional
- Java 1.8.0_101
- Spring Boot 1.4.1
- Spring Framework 4.3.3
参考
- [InterceptorRegistry] (http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/web/servlet/config/annotation/InterceptorRegistry.html)
- [HandlerInterceptorAdapter] (http://docs.spring.io/spring/docs/4.3.3.RELEASE/javadoc-api/org/springframework/web/servlet/handler/HandlerInterceptorAdapter.html)
- [ブラウザのキャッシュコントロールを正しく理解する] (http://qiita.com/hkusu/items/d40aa8a70bacd2015dfa)
- [[spring mvc]ロケールをURL(パス)の一部で切り替える] (http://zero-config.com/java/spring-002.html)
サンプルコード
Interceptor
HandlerInterceptorAdapterを継承して独自のInterceptorを実装します。
MyCustomHandlerInterceptor
public class MyCustomHandlerInterceptor extends HandlerInterceptorAdapter {
@Override
public void postHandle(HttpServletRequest request
, HttpServletResponse response
, Object handler
, ModelAndView modelAndView) throws Exception {
if (!(handler instanceof HandlerMethod)) {
return;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
if (handlerMethod.hasMethodAnnotation(NoCacheAnnotation.class)) {
addNoCacheHeaders(response);
} else if (handlerMethod.hasMethodAnnotation(CacheAnnotation.class)) {
CacheAnnotation annotation = handlerMethod.getMethodAnnotation(CacheAnnotation.class);
int maxAge = (int) AnnotationUtils.getValue(annotation, "maxAge");
addCacheHeaders(response, maxAge);
}
}
private void addNoCacheHeaders(HttpServletResponse response) {
response.addHeader("Cache-Control", "no-store");
}
private void addCacheHeaders(HttpServletResponse response, int maxAge) {
response.addHeader("Cache-Control", "max-age=" + maxAge);
//response.addDateHeader("Expires", new Date().getTime() + (long)(maxAge * 1000));
}
}
Annotation
Response Headerを付加するかどうかを判別するマーカーアノテーションを実装します。
このアノテーションはハンドラーメソッドに付加します。
キャッシュしないハンドラーメソッド用のアノテーション
NoCacheAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface NoCacheAnnotation {
}
キャッシュするハンドラーメソッド用のアノテーション
CacheAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface CacheAnnotation {
public int maxAge();
}
Configuration
WebMvcConfigurerAdapterを継承したクラスを実装して独自のInterceptorを登録します。
@Configuration
public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyCustomHandlerInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/static/**");
}
}
Controller
検証用のコントローラーです。
@Controller
@RequestMapping(value = "/cache")
public class CacheController {
@CacheAnnotation(maxAge = 600)
@RequestMapping(value = "/cache", method = RequestMethod.GET)
public String cache() {
return "cache/cache";
}
@NoCacheAnnotation
@RequestMapping(value = "/nocache", method = RequestMethod.GET)
public String noCache() {
return "cache/nocache";
}
@RequestMapping(value = "/nothing", method = RequestMethod.GET)
public String nothing() {
return "cache/nothing";
}
}
Response Headers
/cache/cache
Cache-Control:max-age=600
Content-Language:ja
Content-Type:text/html;charset=UTF-8
Date:Tue, 08 Nov 2016 17:19:50 GMT
/cache/nocache
HTTP/1.1 200
Cache-Control: no-store
Content-Type: text/html;charset=UTF-8
Content-Language: ja
Transfer-Encoding: chunked
Date: Tue, 08 Nov 2016 17:23:45 GMT
/cache/nothing
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Content-Language: ja
Transfer-Encoding: chunked
Date: Tue, 08 Nov 2016 17:23:24 GMT