Provide controller level Cache-Control support

Prior to this commit, Cache-Control HTTP headers could be set using
a WebContentInterceptor and configured cache mappings.

This commit adds support for cache-related HTTP headers at the controller
method level, by returning a ResponseEntity instance:

ResponseEntity.status(HttpStatus.OK)
    .cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS).cachePublic())
    .eTag("deadb33f8badf00d")
    .body(entity);

Also, this change now automatically checks the "ETag" and
"Last-Modified" headers in ResponseEntity, in order to respond HTTP
"304 - Not Modified" if necessary.

Issue: SPR-8550
This commit is contained in:
Brian Clozel
2015-03-11 11:19:52 +01:00
parent 38f32e3816
commit f9ce11eef8
4 changed files with 209 additions and 7 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.support.WebDataBinderFactory;
@@ -139,12 +140,36 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
}
Object body = responseEntity.getBody();
if (responseEntity instanceof ResponseEntity) {
if (isResourceNotModified(webRequest, (ResponseEntity<?>) responseEntity)) {
// Ensure headers are flushed, no body should be written
outputMessage.flush();
// skip call to converters, as they may update the body
return;
}
}
// Try even with null body. ResponseBodyAdvice could get involved.
writeWithMessageConverters(body, returnType, inputMessage, outputMessage);
// Ensure headers are flushed even if no body was written
outputMessage.getBody();
outputMessage.flush();
}
private boolean isResourceNotModified(NativeWebRequest webRequest, ResponseEntity<?> responseEntity) {
String eTag = responseEntity.getHeaders().getETag();
long lastModified = responseEntity.getHeaders().getLastModified();
boolean notModified = false;
if (lastModified != -1 && StringUtils.hasLength(eTag)) {
notModified = webRequest.checkNotModified(eTag, lastModified);
}
else if (lastModified != -1) {
notModified = webRequest.checkNotModified(lastModified);
}
else if (StringUtils.hasLength(eTag)) {
notModified = webRequest.checkNotModified(eTag);
}
return notModified;
}
@Override