📄 simplemappingexceptionresolver.java
字号:
}
}
}
}
// Else only apply if there are no explicit handler mappings.
return (this.mappedHandlers == null && this.mappedHandlerClasses == null);
}
/**
* Actually resolve the given exception that got thrown during on handler execution,
* returning a ModelAndView that represents a specific error page if appropriate.
* <p>May be overridden in subclasses, in order to apply specific exception checks.
* Note that this template method will be invoked <i>after</i> 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</code> 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 ModelAndView to forward to, or <code>null</code> for default processing
*/
protected ModelAndView doResolveException(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// Log exception, both at debug log level and at warn level, if desired.
if (logger.isDebugEnabled()) {
logger.debug("Resolving exception from handler [" + handler + "]: " + ex);
}
logException(ex, request);
// Expose ModelAndView for chosen error view.
String viewName = determineViewName(ex, request);
if (viewName != null) {
// Apply HTTP status code for error views, if specified.
// Only apply it if we're processing a top-level request.
Integer statusCode = determineStatusCode(request, viewName);
if (statusCode != null) {
applyStatusCodeIfPossible(request, response, statusCode.intValue());
}
return getModelAndView(viewName, ex, request);
}
else {
return null;
}
}
/**
* Log the given exception at warn level, provided that warn logging has been
* activated through the {@link #setWarnLogCategory "warnLogCategory"} property.
* <p>Calls {@link #buildLogMessage} in order to determine the concrete message
* to log. Always passes the full exception to the logger.
* @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), ex);
}
}
/**
* Build a log message for the given exception, occured 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 "Handler execution resulted in exception";
}
/**
* Determine the view name for the given exception, searching the
* {@link #setExceptionMappings "exceptionMappings"}, using the
* {@link #setDefaultErrorView "defaultErrorView"} as fallback.
* @param ex the exception that got thrown during handler execution
* @param request current HTTP request (useful for obtaining metadata)
* @return the resolved view name, or <code>null</code> if none found
*/
protected String determineViewName(Exception ex, HttpServletRequest request) {
String viewName = null;
// Check for specific exception mappings.
if (this.exceptionMappings != null) {
viewName = findMatchingViewName(this.exceptionMappings, ex);
}
// Return default error view else, if defined.
if (viewName == null && this.defaultErrorView != null) {
if (logger.isDebugEnabled()) {
logger.debug("Resolving to default view '" + this.defaultErrorView +
"' for exception of type [" + ex.getClass().getName() + "]");
}
viewName = this.defaultErrorView;
}
return viewName;
}
/**
* Find a matching view name in the given exception mappings.
* @param exceptionMappings mappings between exception class names and error view names
* @param ex the exception that got thrown during handler execution
* @return the view name, or <code>null</code> if none found
* @see #setExceptionMappings
*/
protected String findMatchingViewName(Properties exceptionMappings, Exception ex) {
String viewName = null;
String dominantMapping = null;
int deepest = Integer.MAX_VALUE;
for (Enumeration names = exceptionMappings.propertyNames(); names.hasMoreElements();) {
String exceptionMapping = (String) names.nextElement();
int depth = getDepth(exceptionMapping, ex);
if (depth >= 0 && depth < deepest) {
deepest = depth;
dominantMapping = exceptionMapping;
viewName = exceptionMappings.getProperty(exceptionMapping);
}
}
if (viewName != null && logger.isDebugEnabled()) {
logger.debug("Resolving to view '" + viewName + "' for exception of type [" + ex.getClass().getName() +
"], based on exception mapping [" + dominantMapping + "]");
}
return viewName;
}
/**
* Return the depth to the superclass matching.
* <p>0 means ex matches exactly. Returns -1 if there's no match.
* Otherwise, returns depth. Lowest depth wins.
* <p>Follows the same algorithm as
* {@link org.springframework.transaction.interceptor.RollbackRuleAttribute}.
*/
protected int getDepth(String exceptionMapping, Exception ex) {
return getDepth(exceptionMapping, ex.getClass(), 0);
}
private int getDepth(String exceptionMapping, Class exceptionClass, int depth) {
if (exceptionClass.getName().indexOf(exceptionMapping) != -1) {
// Found it!
return depth;
}
// If we've gone as far as we can go and haven't found it...
if (exceptionClass.equals(Throwable.class)) {
return -1;
}
return getDepth(exceptionMapping, exceptionClass.getSuperclass(), depth + 1);
}
/**
* Determine the HTTP status code to apply for the given error view.
* <p>The default implementation always returns the specified
* {@link #setDefaultStatusCode "defaultStatusCode"}, as a common
* status code for all error views. Override this in a custom subclass
* to determine a specific status code for the given view.
* @param request current HTTP request
* @param viewName the name of the error view
* @return the HTTP status code to use, or <code>null</code> for the
* servlet container's default (200 in case of a standard error view)
* @see #setDefaultStatusCode
* @see #applyStatusCodeIfPossible
*/
protected Integer determineStatusCode(HttpServletRequest request, String viewName) {
return this.defaultStatusCode;
}
/**
* Apply the specified HTTP status code to the given response, if possible
* (that is, if not executing within an include request).
* @param request current HTTP request
* @param response current HTTP response
* @param statusCode the status code to apply
* @see #determineStatusCode
* @see #setDefaultStatusCode
* @see javax.servlet.http.HttpServletResponse#setStatus
*/
protected void applyStatusCodeIfPossible(HttpServletRequest request, HttpServletResponse response, int statusCode) {
if (!WebUtils.isIncludeRequest(request)) {
if (logger.isDebugEnabled()) {
logger.debug("Applying HTTP status code " + statusCode);
}
response.setStatus(statusCode);
}
}
/**
* Return a ModelAndView for the given request, view name and exception.
* <p>The default implementation delegates to {@link #getModelAndView(String, Exception)}.
* @param viewName the name of the error view
* @param ex the exception that got thrown during handler execution
* @param request current HTTP request (useful for obtaining metadata)
* @return the ModelAndView instance
*/
protected ModelAndView getModelAndView(String viewName, Exception ex, HttpServletRequest request) {
return getModelAndView(viewName, ex);
}
/**
* Return a ModelAndView for the given view name and exception.
* <p>The default implementation adds the specified exception attribute.
* Can be overridden in subclasses.
* @param viewName the name of the error view
* @param ex the exception that got thrown during handler execution
* @return the ModelAndView instance
* @see #setExceptionAttribute
*/
protected ModelAndView getModelAndView(String viewName, Exception ex) {
ModelAndView mv = new ModelAndView(viewName);
if (this.exceptionAttribute != null) {
if (logger.isDebugEnabled()) {
logger.debug("Exposing Exception as model attribute '" + this.exceptionAttribute + "'");
}
mv.addObject(this.exceptionAttribute, ex);
}
return mv;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -