【SpringMVC源码】SpringMVC核心DispatcherServlet底层源码分析

17 篇文章 3 订阅
6 篇文章 2 订阅

【SpringMVC源码】SpringMVC核心DispatcherServlet底层源码分析

注:其他一些spring源码解读,如果有需要,可以参考:

1.核心业务流程
  • 直接上图:
    在这里插入图片描述

  • DispatcherServlet是SpringMVC当之无愧的核心,SpringMVC也是用它来处理客户端的请求并将其结果发送至客户端。

  • 为扒源码方便,我们搞个测试Demo:

  • Controller类:

/**
 * todo
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/13
 */
@Controller
public class HelloController {
	
	/**
	 * /WEB-INF/views/success.jsp
	 * @return
	 */
	@RequestMapping("/suc")
	public String success(){
		return "success";
	}
	

}

  • 配置类:
/**
 * SpringMVC只扫描Controller;子容器
 *useDefaultFilters=false 禁用默认的过滤规则;
 * @author wangjie
 * @version V1.0
 * @date 2020/1/13
 */
@ComponentScan(value="com.code",includeFilters={
		@Filter(type=FilterType.ANNOTATION,classes={Controller.class})
},useDefaultFilters=false)
@EnableWebMvc
public class AppConfig  extends WebMvcConfigurerAdapter  {

	/**
	 * 配置视图
	 * @param registry
	 */
	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		//默认所有的页面都从 /WEB-INF/ xxx .jsp
		registry.jsp("/WEB-INF/views/", ".jsp");
	}

	/**
	 * 静态资源访问
	 * @param configurer
	 */
	@Override
	public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
		configurer.enable();
	}


	/**
	 * 拦截器
	 * @param registry
	 */
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(new MyFirstInterceptor()).addPathPatterns("/**");
	}

}

/**
 * Spring的容器不扫描controller;父容器
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/13
 */
@ComponentScan(value="com.code",excludeFilters={
		@Filter(type=FilterType.ANNOTATION,classes={Controller.class})
})
public class RootConfig {

}
/**
 * web容器启动的时候创建对象;调用方法来初始化容器以前前端控制器
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/13
 */
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {


	/**
	 * 获取根容器的配置类;(Spring的配置文件)   父容器
	 * @return
	 */
	@Override
	protected Class<?>[] getRootConfigClasses() {

		return new Class<?>[]{RootConfig.class};
	}


	/**
	 * 获取web容器的配置类(SpringMVC配置文件)  子容器;
	 * @return
	 */
	@Override
	protected Class<?>[] getServletConfigClasses() {

		return new Class<?>[]{AppConfig.class};
	}

	/**
	 * 获取DispatcherServlet的映射信息
	 * /:拦截所有请求(包括静态资源(xx.js,xx.png)),但是不包括*.jsp;
	 * /*:拦截所有请求;连*.jsp页面都拦截;jsp页面是tomcat的jsp引擎解析的;
	 * @return
	 */
	@Override
	protected String[] getServletMappings() {

		return new String[]{"/"};
	}

}
  • 搂草打兔子,再来个拦截器
/**
 * 拦截器
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/13
 */
public class MyFirstInterceptor implements HandlerInterceptor {



	/**
	 * 目标方法运行之前执行
	 * @param request
	 * @param response
	 * @param handler
	 * @return
	 * @throws Exception
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("preHandle..."+request.getRequestURI());
		return true;
	}

	/**
	 * 目标方法执行正确以后执行
	 * @param request
	 * @param response
	 * @param handler
	 * @param modelAndView
	 * @throws Exception
	 */
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
						   ModelAndView modelAndView) throws Exception {

		System.out.println("postHandle...");

	}


	/**
	 * 页面响应以后执行
	 * @param request
	 * @param response
	 * @param handler
	 * @param ex
	 * @throws Exception
	 */
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("afterCompletion...");
	}

}

  • 最后搞个success.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>success!</h1>
</body>

  • 运行效果
    在这里插入图片描述
2.DispatcherServlet底层源码分析
  • 用idea打开DispatcherServlet类图:
    在这里插入图片描述
  • 一路往上看DispatcherServlet继承于FrameworkServlet,FrameworkServlet继承于HttpServletBean,HttpServletBean又继承于HttpServlet
  • 看到HttpServlet我想大家应该多少明白DispatcherServlet是如何起作用了,说到底,它就是一个servlet
  • 是servlet那它就会有我们熟悉的service(),方法,我们从上而下,看是谁重写了service()方法:
  • HttpServletBean没有,再向下。
  • FrameworkServlet:
@Override
	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
		if (HttpMethod.PATCH == httpMethod || httpMethod == null) {
		   //重点
			processRequest(request, response);
		}
		else {
		   //调用父类的方法,再在面
			super.service(request, response);
		}
	}
	 //父类HttpServlet的service
	  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //简单来说就是根据请求类型来调用相应的doXXX()方法,例如doPost(req, resp),doGet(req, resp);
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader("If-Modified-Since");
                if (ifModifiedSince < lastModified / 1000L * 1000L) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
            this.doTrace(req, resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }

    }
   //而d这些oXXX()方法,例如doPost(req, resp),doGet(req, resp);又在FrameworkServlet里被重写,我们再回FrameworkServlet
   @Override
	protected final void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
       //又是它。。。重点
		processRequest(request, response);
	}
	@Override
	protected final void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
      //又是它。。。重点
		processRequest(request, response);
	}

  • service()方法在FrameworkServlet被重写,而在这个被重写的service()方法方法里,忽略那些多余的代码,无论如何调用,都会走到processRequest(request, response);方法
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
        //----------------------------------这些以下不用看---------------------------------
		long startTime = System.currentTimeMillis();
		Throwable failureCause = null;
		LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
		LocaleContext localeContext = buildLocaleContext(request);
		RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
		ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
		asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
		initContextHolders(request, localeContext, requestAttributes);
    //----------------------------------这些以上不用看---------------------------------
		try {
		    //这里,重点
			doService(request, response);
		}
		catch (ServletException ex) {
			failureCause = ex;
			throw ex;
		}
		catch (IOException ex) {
			failureCause = ex;
			throw ex;
		}
		catch (Throwable ex) {
			failureCause = ex;
			throw new NestedServletException("Request processing failed", ex);
		}

		finally {
			resetContextHolders(request, previousLocaleContext, previousAttributes);
			if (requestAttributes != null) {
				requestAttributes.requestCompleted();
			}

			if (logger.isDebugEnabled()) {
				if (failureCause != null) {
					this.logger.debug("Could not complete request", failureCause);
				}
				else {
					if (asyncManager.isConcurrentHandlingStarted()) {
						logger.debug("Leaving response open for concurrent processing");
					}
					else {
						this.logger.debug("Successfully completed request");
					}
				}
			}

			publishRequestHandledEvent(request, response, startTime, failureCause);
		}
	}
  • processRequest()方法只有一行值得我们重视,就是doService(request, response);
  • 我们看FrameworkServlet里的doService(request, response);方法
protected abstract void doService(HttpServletRequest request, HttpServletResponse response)
			throws Exception;
  • 它是个抽象方法,它是实现就在我们今天的主角DispatcherServlet里:
@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
	    //日志记录,不用管
		if (logger.isDebugEnabled()) {
			String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
			logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
					" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
		}

		// 一堆设置,不用看
		Map<String, Object> attributesSnapshot = null;
		if (WebUtils.isIncludeRequest(request)) {
			attributesSnapshot = new HashMap<String, Object>();
			Enumeration<?> attrNames = request.getAttributeNames();
			while (attrNames.hasMoreElements()) {
				String attrName = (String) attrNames.nextElement();
				if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
					attributesSnapshot.put(attrName, request.getAttribute(attrName));
				}
			}
		}

		// 又一堆设置,不看
		request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
		request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
		request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
		request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
		FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
		if (inputFlashMap != null) {
			request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
		}
		request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
		request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

		try {
		  //重点中的核心,核心中的重点
			doDispatch(request, response);
		}
		finally {
			if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
				// Restore the original attribute snapshot, in case of an include.
				if (attributesSnapshot != null) {
					restoreAttributesAfterInclude(request, attributesSnapshot);
				}
			}
		}
	}

  • 排除前面一堆代码不用管,我们只看这个方法里的这一行代码:doDispatch(request, response);
  • 如果说DispatcherServlet是SpringMVC核心,那doDispatch()就是DispatcherServlet的核心,它的地位就像是springIOC容器初始化时的refresh()方法.
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
			  //检查是不是文件上传
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				// 根据当前请求地址找到能处理这个请求的目标处理器
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// 根据当前处理器获取到能执行这个处理器方法的适配器
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}
               //执行所有拦截器的PreHandle方法
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// 执行目标方法,返回一个ModelAndView 对象
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}

				applyDefaultViewName(processedRequest, mv);
				//执行所有拦截器的PostHandle方法
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				// As of 4.3, we're processing Errors thrown from handler methods as well,
				// making them available for @ExceptionHandler methods and other scenarios.
				dispatchException = new NestedServletException("Handler dispatch failed", err);
			}
			//返回响应
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Throwable err) {
			triggerAfterCompletion(processedRequest, response, mappedHandler,
					new NestedServletException("Handler processing failed", err));
		}
		finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				// Instead of postHandle and afterCompletion
				if (mappedHandler != null) {
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// Clean up any resources used by a multipart request.
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}

  • doDispatch()中的重点步骤:

1,getHandler(processedRequest),根据当前请求地址找到能处理这个请求的目标处理器

2,getHandlerAdapter(mappedHandler.getHandler());根据当前处理器获取到能执行这个处理器方法的适配器

3,mappedHandler.applyPreHandle(processedRequest, response)执行所有拦截器的PreHandle方法

4,handle(processedRequest, response, mappedHandler.getHandler());执行目标方法,返回一个ModelAndView 对象

5,mappedHandler.applyPostHandle(processedRequest, response, mv);执行所有拦截器的PostHandle方法

6,processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);返回响应

  • 可以对照着核心流程图看:
    在这里插入图片描述

  • 现在我们就上面的主要步骤一个一个看

2.1 getHandler(processedRequest),根据当前请求地址找到能处理这个请求的目标处理器

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
       //遍历所有的handlerMappings
		for (HandlerMapping hm : this.handlerMappings) {
			if (logger.isTraceEnabled()) {
				logger.trace(
						"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
			}
			//尝试获取跟请求对应的HandlerExecutionChain 
			HandlerExecutionChain handler = hm.getHandler(request);
			if (handler != null) {
			    //返回HandlerExecutionChain 
				return handler;
			}
		}
		return null;
	}
  • 遍历所有的映射器,找到对应的处理执行链返回
  • 我们重新Debug运行测试用例,请求测试地址:
    在这里插入图片描述
  • 我们可以看到handlerMappings映射器处理器有5个
  • 我们继续运行:
    在这里插入图片描述
  • 找到了对应的handlerMappings,返回HandlerExecutionChain 处理器执行链
  • HandlerExecutionChain 中包含了与请求相对应的Controller和拦截器

2.2 getHandlerAdapter(mappedHandler.getHandler());根据当前处理器获取到能执行这个处理器方法的适配器

  • 拿到了对应的HandlerExecutionChain,从里面getHandler()拿到处理器,根据处理器开始找对应的适配器:
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
      //遍历所有适配器
		for (HandlerAdapter ha : this.handlerAdapters) {
			if (logger.isTraceEnabled()) {
				logger.trace("Testing handler adapter [" + ha + "]");
			}
			//判断是否支持当前请求,如果支持,返回该适配器
			if (ha.supports(handler)) {
				return ha;
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}
  • 接着Debug
    在这里插入图片描述
  • handlerAdapters适配器有3种,挨个遍历
    在这里插入图片描述
  • 找到对应适配器,返回

2.3 mappedHandler.applyPreHandle(processedRequest, response)执行所有拦截器的PreHandle方法

  • 我们扒下源码:
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
      //获取所有拦截器
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
		   //挨个遍历
			for (int i = 0; i < interceptors.length; i++) {
				HandlerInterceptor interceptor = interceptors[i];
				//执行拦截器preHandle方法
				if (!interceptor.preHandle(request, response, this.handler)) {
				   //如果执行拦截器preHandle方法返回false
					triggerAfterCompletion(request, response, null);
					return false;
				}
				//记录已执行拦截器数量,后面会用到
				this.interceptorIndex = i;
			}
		}
		//所有拦截器preHandle方法都返回true时返回true
		return true;
	}
	
	/
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
			throws Exception {

		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = this.interceptorIndex; i >= 0; i--) {
				HandlerInterceptor interceptor = interceptors[i];
				try {
				//如果有拦截器preHandle方法返回false,就执行拦截器的afterCompletion()方法
					interceptor.afterCompletion(request, response, this.handler, ex);
				}
				catch (Throwable ex2) {
					logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
				}
			}
		}
	}
  • 注释已经很详细,我们直接Debug:
    在这里插入图片描述
  • 获取所有拦截器,一共拿到3个,其中只有MyFirstInterceptor是我们自定义的,继续执行:
    在这里插入图片描述
  • 遍历到MyFirstInterceptor,我们继续:
    在这里插入图片描述
  • 以此类推,等所有拦截器preHandle方法都返回true时,方法返回
  • 我们可以看一下此时的日志:
[2020-01-17 03:30:41,753] Artifact springmvc-annotation:war: Artifact is deployed successfully
[2020-01-17 03:30:41,754] Artifact springmvc-annotation:war: Deploy took 4,136 milliseconds
preHandle.../suc
  • 完美,我们继续。

2.4 handle(processedRequest, response, mappedHandler.getHandler());执行目标方法,返回一个ModelAndView 对象

  • 源码:
@Override
	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		Class<?> clazz = ClassUtils.getUserClass(handler);
		//获取session注解
		Boolean annotatedWithSessionAttributes = this.sessionAnnotatedClassesCache.get(clazz);
		if (annotatedWithSessionAttributes == null) {
			annotatedWithSessionAttributes = (AnnotationUtils.findAnnotation(clazz, SessionAttributes.class) != null);
			this.sessionAnnotatedClassesCache.put(clazz, annotatedWithSessionAttributes);
		}
        
		if (annotatedWithSessionAttributes) {
			checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
		}
		else {
			checkAndPrepare(request, response, true);
		}

		// 判断是否异步
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					return invokeHandlerMethod(request, response, handler);
				}
			}
		}
       //执行方法,具体细节看下面
		return invokeHandlerMethod(request, response, handler);
	}
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
        //拿到方法的解析器
		ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
		//用方法解析器根据当前请求地址找到真正的执行目标方法
		Method handlerMethod = methodResolver.resolveHandlerMethod(request);
		//创建一个方法执行器
		ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
		//包装原生的request, response
		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		//创建一个隐含模型
		ExtendedModelMap implicitModel = new BindingAwareModelMap();
      //真正的执行目标方法
		Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
		ModelAndView mav =
				methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
		methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
		return mav;
	}
  • 目标方法的执行主要细节都在invokeHandlerMethod()方法里,具体看代码注释

2.5 mappedHandler.applyPostHandle(processedRequest, response, mv);执行所有拦截器的PostHandle方法

  • 源码:
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
        //获取所有源码
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
		   //逆序遍历
			for (int i = interceptors.length - 1; i >= 0; i--) {
			  
				HandlerInterceptor interceptor = interceptors[i];
				//执行拦截器的postHandle方法
				interceptor.postHandle(request, response, this.handler, mv);
			}
		}
	}
  • 跟之前执行拦截器的PreHandle方法一脉相承,唯一需要注意的时,执行顺序是逆序
  • 这里拦截器的执行顺序图
    在这里插入图片描述

2.6 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);返回响应

  • 源码:
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {

		boolean errorView = false;
        //会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理
		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);
			}
		}

		// 重点,渲染视图
		if (mv != null && !mv.wasCleared()) {
		   //渲染视图
			render(mv, request, response);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
		else {
			if (logger.isDebugEnabled()) {
				logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
						"': assuming HandlerAdapter completed request handling");
			}
		}

		if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
	
			return;
		}

		if (mappedHandler != null) {
		  //这个方法在调用拦截器的PreHandle方法返回false时调过,用来调用拦截器的afterCompletion方法
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}
  • 这个方法里首先会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理
  • 然后进行视图渲染
  • 最后执行拦截器的afterCompletion方法
  • 这里的重点就视图渲染 render()方法
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		Locale locale = this.localeResolver.resolveLocale(request);
		response.setLocale(locale);

		View view;
		if (mv.isReference()) {
			// 用系统的视图解析器得到一个view对象.
			view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
			if (view == null) {
				throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
						"' in servlet with name '" + getServletName() + "'");
			}
		}
		else {
			// 不需要查找:ModelAndView对象包含实际的View对象
			view = mv.getView();
			if (view == null) {
				throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
						"View object in servlet with name '" + getServletName() + "'");
			}
		}

		// Delegate to the View object for rendering.
		if (logger.isDebugEnabled()) {
			logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
		}
		try {
			if (mv.getStatus() != null) {
				response.setStatus(mv.getStatus().value());
			}
			//进行视图渲染
			view.render(mv.getModelInternal(), request, response);
		}
		catch (Exception ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
						getServletName() + "'", ex);
			}
			throw ex;
		}
	}
  • 选择一个适合的ViewResolver视图解析器(必须是已经注册到Spring容器中的ViewResolver)拿到一个vew对象
  • 最后进行渲染
3.SpringMVC的九大组件
  • 上面扒源码的时候,出现很多像处理器,适配器,视图解析器。。等一些组件,我们来看看它们都是什么时候初始化的。
  • DispatcherServlet源码
   //文件上传处理器
   private MultipartResolver multipartResolver;

	//区域解析器,更国际化有关
	private LocaleResolver localeResolver;

	//主题解析器
	private ThemeResolver themeResolver;

  //映射器处理器
	private List<HandlerMapping> handlerMappings;

	//适配器
	private List<HandlerAdapter> handlerAdapters;

	//异常处理器
	private List<HandlerExceptionResolver> handlerExceptionResolvers;

	//
	private RequestToViewNameTranslator viewNameTranslator;

	//FlashMap管理器,springMVC重定向携带数据的功能
	private FlashMapManager flashMapManager;

	//视图解析器
	private List<ViewResolver> viewResolvers;
  • 这九大组件都是接口,也是规范。
  • 其初始化过程:
   @Override
	protected void onRefresh(ApplicationContext context) {
		initStrategies(context);
	}
	protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);
		initLocaleResolver(context);
		initThemeResolver(context);
		initHandlerMappings(context);
		initHandlerAdapters(context);
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);
		initFlashMapManager(context);
	}
  • onRefresh方法是spring IOC容器留个子类来实现的,会在容器启动的时候调用,具体详见:

  • 【spring源码】spring IOC容器底层源码分析

  • 我们来看其中几个组件初始化方法:

  • initMultipartResolver(context);初始化文件上传处理器

private void initMultipartResolver(ApplicationContext context) {
		try {
		   //尝试从容器中获得
			this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			// 如果没有就为null;
			this.multipartResolver = null;
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate MultipartResolver with name '" + MULTIPART_RESOLVER_BEAN_NAME +
						"': no multipart request handling provided");
			}
		}
	}
  • initHandlerMappings(context);映射器处理器
private void initHandlerMappings(ApplicationContext context) {
		this.handlerMappings = null;
     
       //detectAllHandlerMappings默认为true
		if (this.detectAllHandlerMappings) {
			//首先尝试根据类型在容器中寻找
			Map<String, HandlerMapping> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
				// We keep HandlerMappings in sorted order.
				AnnotationAwareOrderComparator.sort(this.handlerMappings);
			}
		}
		else {
			try {
			   //如果detectAllHandlerMappings被配置成了false,就根据beanname在容器里找
				HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
				this.handlerMappings = Collections.singletonList(hm);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default HandlerMapping later.
			}
		}

		// 都不行的话就使用默认
		if (this.handlerMappings == null) {
			this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
			if (logger.isDebugEnabled()) {
				logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
			}
		}
	}
  • 首先尝试根据类型在容器中寻找
  • 如果有配置detectAllHandlerMappings被配置成了false,就根据beanname在容器里找
  • 都不行的话就使用默认
  • 其实这九大组件的初始化大都这个套路,想进一步了解可以自己翻翻源码。
  • 要注意的是如果使用默认的话,会使用org.springframework.web.servlet包下的DispatcherServlet.properties配置文件中配置的
# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
4.总结
  • 图解:
    在这里插入图片描述

4.1 描述

    1. 用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获;
    1. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI):
    1. 根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
    1. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。
    1. 如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法【正向】
    1. 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
      ① HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
      ② 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
      ③ 数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
      ④ 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
    1. Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
    1. 此时将开始执行拦截器的postHandle(…)方法【逆向】
    1. 根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet,根据Model和View,来渲染视图
    1. 在返回给客户端时需要执行拦截器的AfterCompletion方法【逆向】
    1. 将渲染结果返回给客户端
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值