0
点赞
收藏
分享

微信扫一扫

SpringMVC源码(二):请求源码流程

绣文字 2022-01-26 阅读 73

SpringMVC具体执行流程

在这里插入图片描述

  1. 用户发送请求至前端控制器DispatcherServlet

  2. DispatcherServlet收到请求调用处理器映射器HandlerMapping
    处理器映射器根据请求url找到具体的处理器,生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)一并返回给DispatcherServlet

  3. DispatcherServlet根据处理器Handler获取处理器适配器
    HandlerAdapter,执行HandlerAdapter处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作

  4. HandlerAdapter执行处理器Handler(Controller,也叫页面控制器)
    Handler执行完成返回ModelAndView, 将执行结果ModelAndView返回到DispatcherServlet

  5. DispatcherServlet将ModelAndView传给ViewReslover视图解析器
    ViewReslover解析后返回具体View

  6. DispatcherServlet对View进行渲染视图(即将模型数据model填充至视图中)

  7. DispatcherServlet响应用户

一个URL请求执行流程

  1. 执行 HttpServlet 的 service(HttpServletRequest req, HttpServletResponse resp) 方法
protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String method = req.getMethod();

        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                if (ifModifiedSince < lastModified) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }

        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);

        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);
            
        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);
            
        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);
            
        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);
            
        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);
            
        } else {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
            //

            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);
            
            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }
  1. 执行demo请求 HttpServlet的doGet(HttpServletRequest req, HttpServletResponse resp)方法 子类 FrameworkServlet
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        process(request, response);
    }
  1. FrameworkServlet的process方法
	protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
			。。。。。。。
			doService(request, response);
			。。。。。。。
	}
  1. FrameworkServlet 子类 DispatcherServlet 的doService(HttpServletRequest request, HttpServletResponse response)方法
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
	.......
	doDispatch(request, response);
	.......
}
  1. DispatcherServlet的doDispatch(HttpServletRequest request, HttpServletResponse response)方法 主方法(重点)
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);

				// DispatcherServlet收到请求调用处理器映射器HandlerMapping
				// 处理器映射器根据请求url找到具体的处理器,生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)
				// 并返回给DispatcherServlet
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// DispatcherServlet根据处理器Handler获取处理器适配器HandlerAdapter
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.  HTTP缓存相关
				String method = request.getMethod();
				boolean isGet = HttpMethod.GET.matches(method);
				if (isGet || HttpMethod.HEAD.matches(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}
				// 前置拦截器
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					// 返回false就不进行后续处理了
					return;
				}

				// 执行HandlerAdapter处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作
				// 执行处理器Handler(Controller,也叫页面控制器)
				// Handler执行完成返回ModelAndView
				// HandlerAdapter将Handler执行结果ModelAndView返回到DispatcherServlet
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}
				// 如果没有视图,给你设置默认视图json忽略
				applyDefaultViewName(processedRequest, mv);
				//后置拦截器
				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);
			}
			// DispatcherServlet将ModelAndView传给ViewReslover视图解析器
			// ViewReslover解析后返回具体View
			// DispatcherServlet对View进行渲染视图(即将模型数据model填充至视图中)
			// DispatcherServlet响应用户
			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);
				}
			}
		}
	}
默认的HandlerMapping根据URL匹配选择合适的
RequestMapping
HandlerMapping
SimpleUrlHandler
MappingBeanNameUrlHandlerMapping

默认的HandlerAdapter根据mappedHandler选择合适的
HttpRequestHandlerAdapter
SimpleControllerHandlerAdapter
RequestMappingHandlerAdapter
HandlerFunctionAdapter

@RequestMapping解析与请求映射
参考流程图: https://www.processon.com/view/link/615ea79e1efad4070b2d6707
执行处理器Handler
  1. 执行处理器Handler, 以RequestMappingHandlerAdapter为例
    执行:
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
	@Override
	protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ModelAndView mav;
		// 检查当前请求的method是否为支持的method(默认Null,可通过继承AbstractController设置supportedMethods)
		// 检查当前请求是否必须session  (默认false,可通过继承AbstractController设置requireSession)
		checkRequest(request);

		/**
		 * 判断当前是否需要支持在同一个session中只能线性地处理请求
		 * 因为锁是通过 synchronized 是 JVM 进程级,所以在分布式环境下,
		 * 无法达到同步相同 Session 的功能。默认情况下,synchronizeOnSession 为 false
		 */
		if (this.synchronizeOnSession) {
			// 获取当前请求的session对象
			HttpSession session = request.getSession(false);
			if (session != null) {
				// 为当前session生成一个唯一的可以用于锁定的key
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					// 对HandlerMethod进行参数等的适配处理,并调用目标handler
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// 如果当前不存在session,则直接对HandlerMethod进行适配
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// *如果当前不需要对session进行同步处理,则直接对HandlerMethod进行适配
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}


		//判断当前请求头中是否包含Cache-Control请求头,如果不包含,则对当前response进行处理
		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			// 如果当前SessionAttribute中存在配置的attributes,则为其设置过期时间。
			// 这里SessionAttribute主要是通过@SessionAttribute注解生成的
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
				// 如果当前不存在SessionAttributes,则判断当前是否存在Cache-Control设置,
				// 如果存在,则按照该设置进行response处理,如果不存在,则设置response中的
				// Cache的过期时间为-1,即立即失效
				prepareResponse(response);
			}
		}

		return mav;
	}
  1. 对HandlerMethod进行适配
	@Nullable
	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
		// 把我们的请求req resp包装成 ServletWebRequest
		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {
			// 获取容器中全局配置的InitBinder和当前HandlerMethod所对应的Controller中
			// 配置的InitBinder,用于进行参数的绑定
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);

			// 获取容器中全局配置的ModelAttribute和当前HandlerMethod所对应的Controller 中配置的ModelAttribute,
			// 这些配置的方法将会在目标方法调用之前进行调用
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

			// 封装handlerMethod,会在调用前解析参数、调用后对返回值进行处理
			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
			if (this.argumentResolvers != null) {
				// 让invocableMethod拥有参数解析能力
				invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
			}
			if (this.returnValueHandlers != null) {
				// 让invocableMethod拥有返回值处理能力
				invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
			}
			// 让invocableMethod拥有InitBinder解析能力
			invocableMethod.setDataBinderFactory(binderFactory);
			// 设置ParameterNameDiscoverer,该对象将按照一定的规则获取当前参数的名称
			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
			// ModelAndView处理容器
			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
			// 将request的Attribute复制一份到ModelMap
			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
			// *调用我们标注了@ModelAttribute的方法,主要是为我们的目标方法预加载
			modelFactory.initModel(webRequest, mavContainer, invocableMethod);
			// 重定向的时候,忽略model中的数据 默认false
			mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

			// 获取当前的AsyncWebRequest,这里AsyncWebRequest的主要作用是用于判断目标
			// handler的返回值是否为WebAsyncTask或DeferredResult,如果是这两种中的一种,
			// 则说明当前请求的处理应该是异步的。所谓的异步,指的是当前请求会将Controller中
			// 封装的业务逻辑放到一个线程池中进行调用,待该调用有返回结果之后再返回到response中。
			// 这种处理的优点在于用于请求分发的线程能够解放出来,从而处理更多的请求,提高吞吐。
			// 只有待目标任务完成之后才会回来将该异步任务的结果返回。
			AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
			asyncWebRequest.setTimeout(this.asyncRequestTimeout);
			// 封装异步任务的线程池、request、interceptors到WebAsyncManager中
			WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
			asyncManager.setTaskExecutor(this.taskExecutor);
			asyncManager.setAsyncWebRequest(asyncWebRequest);
			asyncManager.registerCallableInterceptors(this.callableInterceptors);
			asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

			// 这里就是用于判断当前请求是否有异步任务结果的,如果存在,则对异步任务结果进行封装
			if (asyncManager.hasConcurrentResult()) {
				Object result = asyncManager.getConcurrentResult();
				mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
				asyncManager.clearConcurrentResult();
				LogFormatUtils.traceDebug(logger, traceOn -> {
					String formatted = LogFormatUtils.formatValue(result, !traceOn);
					return "Resume with async result [" + formatted + "]";
				});
				invocableMethod = invocableMethod.wrapConcurrentResult(result);
			}
			// *对请求参数进行处理,调用目标HandlerMethod,并且将返回值封装为一个ModelAndView对象
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			if (asyncManager.isConcurrentHandlingStarted()) {
				return null;
			}

			// 对封装的ModelAndView进行处理,主要是判断当前请求是否进行了重定向,如果进行了重定向,
			// 还会判断是否需要将FlashAttributes封装到新的请求中
			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
			webRequest.requestCompleted();
		}
	}

  1. 对请求参数进行处理,调用目标HandlerMethod,并且将返回值封装为一个ModelAndView对象 ServletInvocableHandlerMethod
    invocableMethod.invokeAndHandle(webRequest, mavContainer)
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {

		/*真正的调用我们的目标对象 很重要 很重要*/
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		// 设置相关的返回状态
		setResponseStatus(webRequest);
		// 如果请求处理完成,则设置requestHandled属性
		if (returnValue == null) {
			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
				disableContentCachingIfNecessary(webRequest);
				mavContainer.setRequestHandled(true);
				return;
			}
		}
		// 如果请求失败,但是有错误原因,那么也会设置requestHandled属性
		else if (StringUtils.hasText(getResponseStatusReason())) {
			mavContainer.setRequestHandled(true);
			return;
		}

		mavContainer.setRequestHandled(false);
		Assert.state(this.returnValueHandlers != null, "No return value handlers");
		try {
			// 遍历当前容器中所有ReturnValueHandler,判断哪种handler支持当前返回值的处理,
			// 如果支持,则使用该handler处理该返回值
			this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}
		catch (Exception ex) {
			if (logger.isTraceEnabled()) {
				logger.trace(formatErrorForReturnValue(returnValue), ex);
			}
			throw ex;
		}
	}
  1. 真正的调用我们的目标对象 很重要 很重要
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
	@Nullable
	public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		//*获取我们目标方法入参的值
		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
		if (logger.isTraceEnabled()) {
			logger.trace("Arguments: " + Arrays.toString(args));
		}
		//真的的调用我们的目标方法
		return doInvoke(args);
	}

doInvoke(args) 反射调用

举报

相关推荐

0 条评论