SpringMVC流程及源代码分析(二)

通过前面一章的分析,我们拿到了HandlerAdapter,然后我们开始进入它的实现类,执行
handle(HttpServletRequest request, HttpServletResponse response, Object handler)
发现其实际调用类为:RequestMappingHandlerAdapter,我们继续分析:

  1. handleInternal(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod)
    这个handlerMethod,就是前面我们最先拿到的HandlerExecutionChain中的handler。方法源码如下:
@Override
	protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ModelAndView mav;
		checkRequest(request);

		// Execute invokeHandlerMethod in synchronized block if required.
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// No HttpSession available -> no mutex necessary
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// 请求会话不需要走同步代码块,我们直接分析invokeHandlerMethod
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
			}
			else {
				prepareResponse(response);
			}
		}

		return mav;
	}
  1. mav = invokeHandlerMethod(request, response, handlerMethod);
@Nullable
	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {
			....
			....
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			if (asyncManager.isConcurrentHandlingStarted()) {
				return null;
			}

			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
			webRequest.requestCompleted();
		}
	}

这一块代码,我们分析invocableMethod.invokeAndHandle(webRequest, mavContainer)和getModelAndView(mavContainer, modelFactory, webRequest);

  1. invocableMethod.invokeAndHandle(webRequest, mavContainer)
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
		//1.执行目标方法,然后返回 返回值 。最终调用 this.getBridgedMethod().invoke(this.getBean(), args) 然后通过反射机制,获取执行请求的返回值
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
		setResponseStatus(webRequest);

		if (returnValue == null) {
			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
				disableContentCachingIfNecessary(webRequest);
				mavContainer.setRequestHandled(true);
				return;
			}
		}
		else if (StringUtils.hasText(getResponseStatusReason())) {
			mavContainer.setRequestHandled(true);
			return;
		}

		mavContainer.setRequestHandled(false);
		Assert.state(this.returnValueHandlers != null, "No return value handlers");
		try {
			//2.处理返回结果returnValue
			this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}
		catch (Exception ex) {
			if (logger.isTraceEnabled()) {
				logger.trace(formatErrorForReturnValue(returnValue), ex);
			}
			throw ex;
		}
	}
  1. getModelAndView(mavContainer, modelFactory, webRequest);
@Nullable
	private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
			ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

		modelFactory.updateModel(webRequest, mavContainer);
		if (mavContainer.isRequestHandled()) {
			return null;
		}
		ModelMap model = mavContainer.getModel();
		//在这边,我们能看见,modelAndView是通过代码自己new出来的,传入了三个参数,viewName,model和status,这三个参数都是通过mavContainer来获取的   第一个参数:viewName mavContainer.getViewName()方法返回viewName,如果view是String类型的实例,那么返回view,否则返回null
		//第二个参数:model mavContainer.getModel(), 得到defaultModel或者是redirectModel,之前在invokeHandlerMethod创建modelFactory的时候就设置了两个参数的值
		//第三个参数:status mavContainer.getStatus(),该方法返回的值的类型是HttpStatus,也就是状态码
		ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
		if (!mavContainer.isViewReference()) {
			mav.setView((View) mavContainer.getView());
		}
		if (model instanceof RedirectAttributes) {
			Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
			HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
			if (request != null) {
				RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
			}
		}
		return mav;
	}
  1. 自此dispatcherServlet中的mv = ha.handle(processedRequest, response, mappedHandler.getHandler());就执行完毕了。总起来说,在这个方法中,执行了反射执行了目标方法,并获取返回值,然后根据mavContainer的属性,来返回mav是null还是ModelAndView。最后呢,就是执行拦截器中的PostHandle。当报错的时候,执行拦截器中的afterCompletion

到此,springmvc的大概源码我们就分析完了。有些不到位的地方,望能指出,一起学习。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值