SpringMVC进阶(三) SpringMVC框架源码深度剖析

一. SpringMVC框架源码剖析准备工作

(一)前段控制器DispatcherServlet继承结构图

SpringMVC进阶(三) SpringMVC框架源码深度剖析_第1张图片

(二)SpringMVC源码剖析准备工作

1. 下载并在IDEA中导入spring-5.1x_ch源码,工程使用Gradle管理

2. 在上述工程中新建一个SpringMVC测试模块

3. 在测试模块的handle方法中打断点,做为SpringMVC请求处理流程的开始

SpringMVC进阶(三) SpringMVC框架源码深度剖析_第2张图片

Debug模式启动Tomcat,在前端发申请,并观察调用栈

SpringMVC进阶(三) SpringMVC框架源码深度剖析_第3张图片

 根据上图得知:doDispathch⽅法中的1064⾏代码完成handler⽅法的调⽤

4. 在success.jsp页面的如下图所示位置打断点,做为流程的结束位置

SpringMVC进阶(三) SpringMVC框架源码深度剖析_第4张图片

 Debug模式启动Tomcat,在前端发申请,并观察调用栈

SpringMVC进阶(三) SpringMVC框架源码深度剖析_第5张图片

 如上图得知:SpringMVC处理请求的全流程即为org.springframework.web.servlet.DispatcherServlet#doDispatch⽅法的执⾏过程。

因此整个源码的剖析以DispatcherServlet前端控制器中的doDispatch⽅法为主。

5.阅读分析源码时参照以下SpringMVC请求处理流程图

SpringMVC进阶(三) SpringMVC框架源码深度剖析_第6张图片

 

二. SpringMVC处理请求的流程源码剖析

(一)DispatcherServlet类中的doDispatch方法源码示例

/**
	 * Process the actual dispatching to the handler.
	 * 

The handler will be obtained by applying the servlet's HandlerMappings in order. * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters * to find the first that supports the handler class. *

All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers * themselves to decide which methods are acceptable. * @param request current HTTP request * @param response current HTTP response * @throws Exception in case of any kind of processing failure */ 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 { // 1 检查是否是文件上传的请求 processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. /* 2 取得处理当前请求的Controller,这里也称为Handler,即处理器 这里并不是直接返回 Controller,而是返回 HandlerExecutionChain 请求处理链对象 该对象封装了Handler和Inteceptor */ mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { // 如果 handler 为空,则返回404 noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. // 3 获取处理请求的处理器适配器 HandlerAdapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. // 处理 last-modified 请求头 String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } //SpringMVC拦截器(Handler执行之前拦截一次) if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. // 4 实际处理器处理请求,返回结果视图对象 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } // 结果视图对象的处理 applyDefaultViewName(processedRequest, mv); //SpringMVC拦截器(Handler执行之后,跳转页面之前拦截一次) 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); } //5.跳转页面,渲染视图 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { //最终会调用HandlerInterceptor的afterCompletion 方法 triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { //最终会调用HandlerInterceptor的afterCompletion 方法 //SpringMVC拦截器(跳转页面之后拦截一次) 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); } } } }

(二) 通过以上源码展示得出以下执行步骤

步骤一: 检查是否是文件上传的请求

步骤二:调⽤getHandler()(核心步骤)

取得处理当前请求的Controller,这里也称为Handler,即处理器,这里并不是直接返回 Controller,而是返回 HandlerExecutionChain 请求处理链对象,该对象封装了Handler和Inteceptor。

步骤三:调⽤getHandlerAdapter()(核心步骤)

获取能够执⾏步骤一Handler的适配器。

步骤四:适配器调⽤Handler执⾏ha.handle(核心步骤)

总会返回⼀个ModelAndView对象。

步骤五:调⽤processDispatchResult()(核心步骤)

完成视图渲染,页面跳转。

三. SpringMVC核心步骤源码剖析

(一)步骤二:getHandler()方法剖析

1. 代码示例

/**
	 * Return the HandlerExecutionChain for this request.
	 * 

Tries all handler mappings in order. * @param request current HTTP request * @return the HandlerExecutionChain, or {@code null} if no handler could be found */ @Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { for (HandlerMapping mapping : this.handlerMappings) { HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }

2. 代码分析

SpringMVC进阶(三) SpringMVC框架源码深度剖析_第7张图片

 图中需要遍历两个HandlerMapping,试图获取能够处理当前请求的执⾏链。

(二)步骤三:getHandlerAdapter⽅法剖析

1. 代码示例

/**
	 * Return the HandlerAdapter for this handler object.
	 * @param handler the handler object to find an adapter for
	 * @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
	 */
	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
				if (adapter.supports(handler)) {
					return adapter;
				}
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

(三)步骤四:ha.handle⽅法剖析

SpringMVC进阶(三) SpringMVC框架源码深度剖析_第8张图片

 如图执行的handle就是我们定义的handle01

断点从入口进入

SpringMVC进阶(三) SpringMVC框架源码深度剖析_第9张图片

 发现返回的是handleInternal方法的返回值,继续进入handleInternal方法

@Override
	protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ModelAndView mav;
		checkRequest(request);

		// Execute invokeHandlerMethod in synchronized block if required.
		// 判断当前是否需要支持在同一个session中只能线性地处理请求
		if (this.synchronizeOnSession) {
			// 获取当前请求的session对象
			HttpSession session = request.getSession(false);
			if (se

你可能感兴趣的:(JAVA进阶笔记整理,java,spring,intellij-idea,springMVC源码解析)