diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerExceptionResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerExceptionResolver.java index c6fdec3ae8..856d0b62db 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerExceptionResolver.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerExceptionResolver.java @@ -34,10 +34,18 @@ import org.springframework.web.servlet.ModelAndView; * and the {@link Ordered} implementation. * * @author Arjen Poutsma + * @author Juergen Hoeller * @since 3.0 */ public abstract class AbstractHandlerExceptionResolver implements HandlerExceptionResolver, Ordered { + private static final String HEADER_PRAGMA = "Pragma"; + + private static final String HEADER_EXPIRES = "Expires"; + + private static final String HEADER_CACHE_CONTROL = "Cache-Control"; + + /** Logger available to subclasses */ protected final Log logger = LogFactory.getLog(getClass()); @@ -49,6 +57,8 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti private Log warnLogger; + private boolean preventResponseCaching = false; + public void setOrder(int order) { this.order = order; @@ -59,32 +69,36 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti } /** - * Specify the set of handlers that this exception resolver should apply to. The exception mappings and the default - * error view will only apply to the specified handlers.
If no handlers and handler classes are set, the exception - * mappings and the default error view will apply to all handlers. This means that a specified default error view will - * be used as fallback for all exceptions; any further HandlerExceptionResolvers in the chain will be ignored in this - * case. + * Specify the set of handlers that this exception resolver should apply to. + * The exception mappings and the default error view will only apply to the specified handlers. + *
If no handlers and handler classes are set, the exception mappings and the default error + * view will apply to all handlers. This means that a specified default error view will be used + * as fallback for all exceptions; any further HandlerExceptionResolvers in the chain will be + * ignored in this case. */ public void setMappedHandlers(Set mappedHandlers) { this.mappedHandlers = mappedHandlers; } /** - * Specify the set of classes that this exception resolver should apply to. The exception mappings and the default - * error view will only apply to handlers of the specified type; the specified types may be interfaces and superclasses - * of handlers as well.
If no handlers and handler classes are set, the exception mappings and the default error - * view will apply to all handlers. This means that a specified default error view will be used as fallback for all - * exceptions; any further HandlerExceptionResolvers in the chain will be ignored in this case. + * Specify the set of classes that this exception resolver should apply to. + * The exception mappings and the default error view will only apply to handlers of the + * specified type; the specified types may be interfaces and superclasses of handlers as well. + *
If no handlers and handler classes are set, the exception mappings and the default error + * view will apply to all handlers. This means that a specified default error view will be used + * as fallback for all exceptions; any further HandlerExceptionResolvers in the chain will be + * ignored in this case. */ public void setMappedHandlerClasses(Class[] mappedHandlerClasses) { this.mappedHandlerClasses = mappedHandlerClasses; } /** - * Set the log category for warn logging. The name will be passed to the underlying logger implementation through - * Commons Logging, getting interpreted as log category according to the logger's configuration.
Default is no warn - * logging. Specify this setting to activate warn logging into a specific category. Alternatively, override the {@link - * #logException} method for custom logging. + * Set the log category for warn logging. The name will be passed to the underlying logger + * implementation through Commons Logging, getting interpreted as log category according + * to the logger's configuration. + *
Default is no warn logging. Specify this setting to activate warn logging into a specific + * category. Alternatively, override the {@link #logException} method for custom logging. * @see org.apache.commons.logging.LogFactory#getLog(String) * @see org.apache.log4j.Logger#getLogger(String) * @see java.util.logging.Logger#getLogger(String) @@ -93,6 +107,16 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti this.warnLogger = LogFactory.getLog(loggerName); } + /** + * Specify whether to prevent HTTP response caching for any view resolved + * by this HandlerExceptionResolver. + *
Default is "false". Switch this to "true" in order to automatically + * generate HTTP response headers that suppress response caching. + */ + public void setPreventResponseCaching(boolean preventResponseCaching) { + this.preventResponseCaching = preventResponseCaching; + } + /** * Checks whether this resolver is supposed to apply (i.e. the handler matches @@ -108,6 +132,7 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti logger.debug("Resolving exception from handler [" + handler + "]: " + ex); } logException(ex, request); + prepareResponse(ex, response); return doResolveException(request, response, handler, ex); } else { @@ -171,6 +196,34 @@ public abstract class AbstractHandlerExceptionResolver implements HandlerExcepti return "Handler execution resulted in exception"; } + /** + * Prepare the response for the exceptional case. + *
The default implementation prevents the response from being cached,
+ * if the {@link #setPreventResponseCaching "preventResponseCaching"} property
+ * has been set to "true".
+ * @param ex the exception that got thrown during handler execution
+ * @param response current HTTP response
+ * @see #preventCaching
+ */
+ protected void prepareResponse(Exception ex, HttpServletResponse response) {
+ if (this.preventResponseCaching) {
+ preventCaching(response);
+ }
+ }
+
+ /**
+ * Prevents the response from being cached, through setting corresponding
+ * HTTP headers. See http://www.mnot.net/cache_docs.
+ * @param response current HTTP response
+ */
+ protected void preventCaching(HttpServletResponse response) {
+ response.setHeader(HEADER_PRAGMA, "no-cache");
+ response.setDateHeader(HEADER_EXPIRES, 1L);
+ response.setHeader(HEADER_CACHE_CONTROL, "no-cache");
+ response.addHeader(HEADER_CACHE_CONTROL, "no-store");
+ }
+
+
/**
* Actually resolve the given exception that got thrown during on handler execution,
* returning a ModelAndView that represents a specific error page if appropriate.