SpringMVC执行流程,源码分析(三)

后置处理器

/* 参见异步的文章 */
if (asyncManager.isConcurrentHandlingStarted()) {
	return;
}
applyDefaultViewName(processedRequest, mv);
/* 后置处理器 */
mappedHandler.applyPostHandle(processedRequest, response, mv);

处理结果

request的处理结果以及该请求过程中可能发生的异常
处理结果.png

如果发生了异常

if (exception != null) {
	/* 视图需要转发 */
	if (exception instanceof ModelAndViewDefiningException) {
		logger.debug("ModelAndViewDefiningException encountered", exception);
		mv = ((ModelAndViewDefiningException) exception).getModelAndView();
	}
	else {
		Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
		/* 处理异常 */
		mv = processHandlerException(request, response, handler, exception);
		errorView = (mv != null);
	}
}

异常处理器.png

可以看到,一旦某个异常处理器返回了视图,后续的异常处理器都不会被调用
默认有两个HandlerExceptionResolver

  • DefaultErrorAttributes,将异常保存到域中,返回null
  • HandlerExceptionResolverComposite,委托给另外三个resolver实现
    • ExceptionHandlerExceptionResolver,通常说的全局异常处理器,Spring启动时,会扫描ControllerAdvice注解,然后收集其中的异常与对应的处理方法。
      我们指定的全局异常处理器的方法,其实和控制器的方法差不多,走的执行流程也相似。
    • ResponseStatusExceptionResolver,要处理的异常被@ResponseStatus注解,调用该处理器
    if (ex instanceof ResponseStatusException) {
    		return resolveResponseStatusException((ResponseStatusException) ex, request, response, handler);
    	}
    
    	ResponseStatus status = AnnotatedElementUtils.findMergedAnnotation(ex.getClass(), ResponseStatus.class);
    	if (status != null) {
    		return resolveResponseStatus(status, request, response, handler, ex);
    	}
    
    	if (ex.getCause() instanceof Exception) {
    		return doResolveException(request, response, handler, (Exception) ex.getCause());
    	}
    
    • DefaultHandlerExceptionResolver,当上面处理器都没能处理异常后,走默认处理逻辑,类似我们看到的tomcat的默认蓝色的错误页或者白色一堆报错或者json格式,依据客户端Accept而定,该处理器就是一堆if else判断异常原因,返回视图

处理视图

如果此时视图不为null,可能是未发生异常或者处理异常后返回了视图
如果视图为null,那么返回的内容不是视图

// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
	render(mv, request, response);
	if (errorView) {
		WebUtils.clearErrorRequestAttributes(request);
	}
}

在render函数中,模板引擎开始工作

拦截器-已完成

if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
	// Concurrent handling started during a forward
	return;
}

if (mappedHandler != null) {
	// Exception (if any) is already handled..
	mappedHandler.triggerAfterCompletion(request, response, null);
}

至此,拦截器三个方法都被调用了。

到此,差不多分析完成了,略过了很多异步的内容,打算单独写一篇文章分析

Q.E.D.


一切很好,不缺烦恼。