All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver Maven / Gradle / Ivy

There is a newer version: 6.1.6
Show newest version
/*
 * Copyright 2002-2020 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.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.servlet.handler;

import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

/**
 * Abstract base class for {@link HandlerExceptionResolver} implementations.
 *
 * 

Supports mapped {@linkplain #setMappedHandlers handlers} and * {@linkplain #setMappedHandlerClasses handler classes} that the resolver * should be applied to and implements the {@link Ordered} interface. * * @author Arjen Poutsma * @author Juergen Hoeller * @author Sam Brannen * @since 3.0 */ public abstract class AbstractHandlerExceptionResolver implements HandlerExceptionResolver, Ordered { private static final String HEADER_CACHE_CONTROL = "Cache-Control"; /** Logger available to subclasses. */ protected final Log logger = LogFactory.getLog(getClass()); private int order = Ordered.LOWEST_PRECEDENCE; @Nullable private Set mappedHandlers; @Nullable private Class[] mappedHandlerClasses; @Nullable private Log warnLogger; private boolean preventResponseCaching = false; public void setOrder(int order) { this.order = order; } @Override public int getOrder() { return this.order; } /** * 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 or 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 a 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 types; the specified types may be interfaces or superclasses of handlers as well. *

If no handlers or 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 a 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 a log category according * to the logger's configuration. If {@code null} or empty String is passed, warn logging * is turned off. *

By default there is no warn logging although subclasses like * {@link org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver} * can change that default. 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 java.util.logging.Logger#getLogger(String) */ public void setWarnLogCategory(String loggerName) { this.warnLogger = (StringUtils.hasLength(loggerName) ? LogFactory.getLog(loggerName) : null); } /** * Specify whether to prevent HTTP response caching for any view resolved * by this exception resolver. *

Default is {@code false}. Switch this to {@code true} in order to * automatically generate HTTP response headers that suppress response caching. */ public void setPreventResponseCaching(boolean preventResponseCaching) { this.preventResponseCaching = preventResponseCaching; } /** * Check whether this resolver is supposed to apply (i.e. if the supplied handler * matches any of the configured {@linkplain #setMappedHandlers handlers} or * {@linkplain #setMappedHandlerClasses handler classes}), and then delegate * to the {@link #doResolveException} template method. */ @Override @Nullable public ModelAndView resolveException( HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) { if (shouldApplyTo(request, handler)) { prepareResponse(ex, response); ModelAndView result = doResolveException(request, response, handler, ex); if (result != null) { // Print debug message when warn logger is not enabled. if (logger.isDebugEnabled() && (this.warnLogger == null || !this.warnLogger.isWarnEnabled())) { logger.debug("Resolved [" + ex + "]" + (result.isEmpty() ? "" : " to " + result)); } // Explicitly configured warn logger in logException method. logException(ex, request); } return result; } else { return null; } } /** * Check whether this resolver is supposed to apply to the given handler. *

The default implementation checks against the configured * {@linkplain #setMappedHandlers handlers} and * {@linkplain #setMappedHandlerClasses handler classes}, if any. * @param request current HTTP request * @param handler the executed handler, or {@code null} if none chosen * at the time of the exception (for example, if multipart resolution failed) * @return whether this resolved should proceed with resolving the exception * for the given request and handler * @see #setMappedHandlers * @see #setMappedHandlerClasses */ protected boolean shouldApplyTo(HttpServletRequest request, @Nullable Object handler) { if (handler != null) { if (this.mappedHandlers != null && this.mappedHandlers.contains(handler)) { return true; } if (this.mappedHandlerClasses != null) { for (Class handlerClass : this.mappedHandlerClasses) { if (handlerClass.isInstance(handler)) { return true; } } } } return !hasHandlerMappings(); } /** * Whether there are any handler mappings registered via * {@link #setMappedHandlers(Set)} or {@link #setMappedHandlerClasses(Class[])}. * @since 5.3 */ protected boolean hasHandlerMappings() { return (this.mappedHandlers != null || this.mappedHandlerClasses != null); } /** * Log the given exception at warn level, provided that warn logging has been * activated through the {@link #setWarnLogCategory "warnLogCategory"} property. *

Calls {@link #buildLogMessage} in order to determine the concrete message to log. * @param ex the exception that got thrown during handler execution * @param request current HTTP request (useful for obtaining metadata) * @see #setWarnLogCategory * @see #buildLogMessage * @see org.apache.commons.logging.Log#warn(Object, Throwable) */ protected void logException(Exception ex, HttpServletRequest request) { if (this.warnLogger != null && this.warnLogger.isWarnEnabled()) { this.warnLogger.warn(buildLogMessage(ex, request)); } } /** * Build a log message for the given exception, occurred during processing the given request. * @param ex the exception that got thrown during handler execution * @param request current HTTP request (useful for obtaining metadata) * @return the log message to use */ protected String buildLogMessage(Exception ex, HttpServletRequest request) { return "Resolved [" + ex + "]"; } /** * 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 {@code Cache-Control: no-store} header. * @param response current HTTP response */ protected void preventCaching(HttpServletResponse response) { response.addHeader(HEADER_CACHE_CONTROL, "no-store"); } /** * Actually resolve the given exception that got thrown during handler execution, * returning a {@link ModelAndView} that represents a specific error page if appropriate. *

May be overridden in subclasses, in order to apply specific exception checks. * Note that this template method will be invoked after checking whether this * resolved applies ("mappedHandlers" etc), so an implementation may simply proceed * with its actual exception handling. * @param request current HTTP request * @param response current HTTP response * @param handler the executed handler, or {@code null} if none chosen at the time * of the exception (for example, if multipart resolution failed) * @param ex the exception that got thrown during handler execution * @return a corresponding {@code ModelAndView} to forward to, * or {@code null} for default processing in the resolution chain */ @Nullable protected abstract ModelAndView doResolveException( HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy