Spring source code learning series 3.2.3 - exception page interception mechanism

Preface: The significance of this article is to understand that when tomcat handles exception


requests to access the background, it is not smooth sailing. Sometimes an error may occur during model-driven binding, or an exception may occur while executing the target method. How does springmvc handle these unknowable exceptions?


According to the analysis of the source code of the last method of <spring source code learning series 3.2-handlerAdapter execution>, you can simply understand how springmvc handles these exceptions

MultiActionController#handleRequestInternal
@Override
	protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		try {
			String methodName = this.methodNameResolver.getHandlerMethodName(request);
			return invokeNamedMethod(methodName, request, response);
		}
		catch (NoSuchRequestHandlingMethodException ex) {
			return handleNoSuchRequestHandlingMethod(ex, request, response);
		}
	}

If the thrown exception is NoSuchRequestHandlingMethodException, return a 404 error


MultiActionController#invokeNamedMethod
protected final ModelAndView invokeNamedMethod(  
            String methodName, HttpServletRequest request, HttpServletResponse response) throws Exception {  
  
//Get the method execution body, handlerMethodMap is initialized in the constructor  
        Method method = this.handlerMethodMap.get(methodName);  
        if (method == null) {  
            throw new NoSuchRequestHandlingMethodException(methodName, getClass());  
        }  
  
        try {  
           ......
        }  
        catch (InvocationTargetException ex) {  
            // The handler method threw an exception.  
            return handleException(request, response, ex.getTargetException());  
        }  
        catch (Exception ex) {  
            // The binding process threw an exception.  
            return handleException(request, response, ex);  
        }  
    }  



MultiActionController#handleException
private ModelAndView handleException(HttpServletRequest request, HttpServletResponse response, Throwable ex)
			throws Exception {

		Method handler = getExceptionHandler(ex);
		if (handler != null) {
			if (logger.isDebugEnabled()) {
				logger.debug("Invoking exception handler [" + handler + "] for exception: " + ex);
			}
			try {
				Object returnValue = handler.invoke(this.delegate, request, response, ex);
				return massageReturnValueIfNecessary(returnValue);
			}
			catch (InvocationTargetException ex2) {
				logger.error("Original exception overridden by exception handling failure", ex);
				ReflectionUtils.rethrowException(ex2.getTargetException());
			}
			catch (Exception ex2) {
				logger.error("Failed to invoke exception handler method", ex2);
			}
		}
		else {
			// If we get here, there was no custom handler or we couldn't invoke it.
			ReflectionUtils.rethrowException(ex);
		}
		throw new IllegalStateException("Should never get here");
	}

From here, we can see that springmvc handles exceptions by customizing the processing method, and continuing to throw exceptions

----------------------- ------------------------ springmvc handles exceptions
1. Custom processing method
MultiActionController#getExceptionHandler
protected Method getExceptionHandler(Throwable exception) {
		Class exceptionClass = exception.getClass();
		if (logger.isDebugEnabled()) {
			logger.debug("Trying to find handler for exception class [" + exceptionClass.getName() + "]");
		}
		Method handler = this.exceptionHandlerMap.get(exceptionClass);
		while (handler == null && !exceptionClass.equals(Throwable.class)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Trying to find handler for exception superclass [" + exceptionClass.getName() + "]");
			}
			exceptionClass = exceptionClass.getSuperclass();
			handler = this.exceptionHandlerMap.get(exceptionClass);
		}
		return handler;
	}

When initializing the controller, the exceptionHandlerMap is registered. The method in the custom controller that conforms to the format will be registered as an exception handling method

private boolean isExceptionHandlerMethod(Method method) {
		return (isHandlerMethod(method) &&
				method.getParameterTypes().length == 3 &&
				Throwable.class.isAssignableFrom(method.getParameterTypes()[2]));
	}

Exception handling method conditions:
a. The first parameter is HttpServletRequest, the second parameter is HttpServletResponse, and the third parameter is a subclass of Throwable

b. Return type ModelAndView Map String or void





----------- ---------------------------------------- tomcat handles exceptions
2. Throws an exception, let The tomcat processing
user (developer) can set the error code (response.setErrorCode) in the program (web.xml), and locate the thrown exception to a more user-friendly interface, such as:
<error-page>
<error-code>404</error-code>
<location>/errorpages/404.jsp</location>
</error-page>  

<error-page>
  <exception-type>Java.lang.Exception</exception-type>
  <location>/errorpages/exception.jsp</location>
 </error-page>

When the application starts, parse web.xml , set the page corresponding to the error code or exception to errorPage, and set it to the properties of the Context application. An exception occurs in the subsequent program and an exception is thrown during the StandardHostValve processing. In



the entire request processing process , a series of Valves will be included in the Pipeline, including two values ​​StandardHostValve and ErrorReportValve

StandardHostValve is to call the errorPage configured in web.xml and return it to the browser
StandardHostValve# throwable
        
    protected void throwable(Request request, Response response,
                             Throwable throwable) {
        .........
        ErrorPage errorPage = findErrorPage(context, throwable);
        if ((errorPage == null) && (realError != throwable)) {
            errorPage = findErrorPage(context, realError);
        }

        if (errorPage != null) {
            response.setAppCommitted(false);
            request.setAttribute
                (ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
                 errorPage.getLocation());
            request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
                              DispatcherType.ERROR);
            request.setAttribute
                (Globals.STATUS_CODE_ATTR,
                 new Integer(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
            request.setAttribute(Globals.ERROR_MESSAGE_ATTR,
                              throwable.getMessage());
            request.setAttribute(Globals.EXCEPTION_ATTR,
                              realError);
            Wrapper wrapper = request.getWrapper();
            if (wrapper != null)
                request.setAttribute(Globals.SERVLET_NAME_ATTR,
                                  wrapper.getName());
            request.setAttribute(Globals.EXCEPTION_PAGE_ATTR,
                                 request.getRequestURI());
            request.setAttribute(Globals.EXCEPTION_TYPE_ATTR,
                              realError.getClass());
            if (custom(request, response, errorPage)) {
                try {
                    response.flushBuffer();
                } catch (IOException e) {
                    container.getLogger().warn("Exception Processing " + errorPage, e);
                }
            }
        } .......

    }


If there is no configuration, the error page is hard-coded in ErrorReportValve to generate an exception page and returned to the browser




StandardHostValve source code
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/ org/apache/catalina/core/StandardHostValve.java

ErrorReportValve source code:
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/tomcat-catalina/7.0.0/org/apache/ catalina/valves/ErrorReportValve.java#ErrorReportValve


Reference:
Your error page. No, it's your error page
http://www.10tiao.com/html/142/201610/2650859268/1.html

Tomcat's ErrorPage implementation principle analysishttp ://www.cnblogs.com/softidea/p/5981766
. html

Tomcat's error exception status returns to the report page Error Report Valve (Valve Source Code Analysis No. 8
http://www.10tiao.com/html/308/201702/2650076436/1.html

[Tomcat source code learning]-3. Application management
http://www.cnblogs.com/hframe/p/5326352.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326363278&siteId=291194637