I have an Api endpoint with Spring 5 as @RestController and I want to specify the Cache-Control for all endpoints at once (via a Config or an Annotation,...).
Currently I do this on every single method. I also had to use ResponseEntity to set the Cache-Control which bloats the code even more.
@RestController
@RequestMapping("/api")
public class MyApi {
@PostMapping("/search")
public ResponseEntity<SearchResultDto> search(SearchDto searchDto) {
// ...
return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(20, TimeUnit.SECONDS))
.body(searchResultDto);
}
@GetMapping("/get")
public ResponseEntity<EntityDto> get(Long id) {
// ...
return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(20, TimeUnit.SECONDS))
.body(entityDto);
}
// ... more methods
}
- I tried Aspects, but it is not possible to alter the http headers after they are created.
@Aspect
@Component
public class CacheAspect {
@Pointcut("within(io.company.MyApi)")
public void apiMethods() {
}
@Around("apiMethods()")
public Object addCacheControlOnResponseEntity(ProceedingJoinPoint pjp) throws Throwable {
Object retval = pjp.proceed();
if (retval instanceof ResponseEntity) {
((ResponseEntity) retval).getHeaders().setCacheControl(CacheControl.maxAge(15, TimeUnit.SECONDS));
// exception is thrown, because map can not be modified anymore
}
return retval;
}
}
- I tried interceptors (HandlerInterceptor), but here it is the same problem, that the http headers can not be modified afterwards.
@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
response.setHeader(HttpHeaders.CACHE_CONTROL, CacheControl.maxAge(2, TimeUnit.SECONDS).getHeaderValue());
// header does not get modified
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
response.setHeader(HttpHeaders.CACHE_CONTROL, CacheControl.maxAge(2, TimeUnit.SECONDS).getHeaderValue());
// header does not get modified
}
});
}
}
- I tried to add a resource handler (ResourceHandler) (for usually static content) and set the caching strategy for /api/**, but it was not applied.
@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/api/**")
.setCacheControl(CacheControl.maxAge(10, TimeUnit.SECONDS));
// didn't had any effect
}
}
... I am out of ideas
What can I do to write less duplicate/boilerplate code?