SpringMVC 执行流程源码解析


办公设备租赁,深圳惠源.

前言

SpringMVC提供了统一的入口DispatcherServlet,有该Servlet分发到各处理器并返回视图,所以从DispatcherServlet开始分析即可。


一、DispatcherServlet

包含了SpringMVC 的整个执行流程,从DispatcherServlet的继承结构和方法调用栈可以看到最终会到DispatcherServlet的doServcie方法开始执行,所以从doServcie方法开始分析。
在这里插入图片描述
在这里插入图片描述

1、doServcie

		// 设置常用实例到request属性域
		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());
		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);
				}
			}
		}

2、doDispatch

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 {
			    // 判断并处理文件请求-MultipartHttpServletRequest contentType.toLowerCase().startsWith("multipart/");
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				// 获取Handler 
				mappedHandler = getHandler(processedRequest);

				// 获取处理器适配器,由于处理器不一样,有Controller类型,方法类型,所以需要由适配器来进行适配执行
				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 (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}
				
				// 执行MVC拦截器得前置方法 如果前置方法返回false,则表示不执行业务方法
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// 适配器执行handler业务方法 以 RequestMappingHandlerAdapter 分析
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

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

				applyDefaultViewName(processedRequest, mv);
				// 执行MVC拦截器得后置方法
				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);
			}
			// 处理返回结果 ModelView
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
		// 执行MVC 拦截器得afterCompletion
			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);
				}
			}
		}
	}

3、getHandler

遍历循环当前所有HandlerMapping获取处理器
在这里插入图片描述

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;
	}

4、getHandlerAdapter

获取处理器适配器,由于Handler,可能是Controller,也可能是Method,所以需要适配器进行适配。
在这里插入图片描述

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
				// 判断是否是该适配器进行适配 以HttpRequestHandlerAdapter进行分析
				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");
	}

5、applyPreHandle

执行拦截器前置处理。

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];
				// 执行拦截器前置,由个拦截器自己实现拉
				if (!interceptor.preHandle(request, response, this.handler)) {
					// 触发执行拦截器的afterCompletion
					triggerAfterCompletion(request, response, null);
					return false;
				}
				this.interceptorIndex = i;
			}
		}
		return true;
	}

6、handle

业务方法执行。

public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return handleInternal(request, response, (HandlerMethod) handler);
	}

6、processDispatchResult

处理返回结果/异常/MV

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
			@Nullable 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);
			}
		}

		// 是否返回了一个ModelAndView
		if (mv != null && !mv.wasCleared()) {
			// 渲染ModelAndView
			render(mv, request, response);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("No view rendering, null ModelAndView returned.");
			}
		}

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

		if (mappedHandler != null) {
			// 执行拦截器的AfterComplete方法
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}

7、render

渲染视图

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
		// Determine locale for request and apply it to the response.
		Locale locale =
				(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
		response.setLocale(locale);

		View view;
		String viewName = mv.getViewName();
		if (viewName != null) {
			// 通过ViewResolver解析View
			view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
			if (view == null) {
				throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
						"' in servlet with name '" + getServletName() + "'");
			}
		}
		else {
			// No need to lookup: the ModelAndView object contains the actual View object.
			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.isTraceEnabled()) {
			logger.trace("Rendering view [" + view + "] ");
		}
		try {
			if (mv.getStatus() != null) {
				response.setStatus(mv.getStatus().value());
			}
			// 由view来具体实现渲染视图
			view.render(mv.getModelInternal(), request, response);
		}
		catch (Exception ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Error rendering view [" + view + "]", ex);
			}
			throw ex;
		}
	}

二、AbstractHandlerMapping

抽象AbstractHandlerMapping,由具体子类去实现getHandlerInternal,并封装返回执行器链

1、getHandler

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		// 获取具体得Handler,由子类实现,以下分析下通用得RequestMappingHandlerMapping
		Object handler = getHandlerInternal(request);
		if (handler == null) {
			handler = getDefaultHandler();
		}
		if (handler == null) {
			return null;
		}
		// Bean name or resolved handler?
		if (handler instanceof String) {
			String handlerName = (String) handler;
			handler = obtainApplicationContext().getBean(handlerName);
		}

		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

		if (logger.isTraceEnabled()) {
			logger.trace("Mapped to " + handler);
		}
		else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
			logger.debug("Mapped to " + executionChain.getHandler());
		}

		if (hasCorsConfigurationSource(handler)) {
			CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
			CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
			config = (config != null ? config.combine(handlerConfig) : handlerConfig);
			executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
		}

		return executionChain;
	}

三、RequestMappingHandlerMapping

1、afterPropertiesSet

由于RequestMappingHandlerMapping实现了InitializingBean,该方法在RequestMappingHandlerMapping实例化后会被Spring调用。设置urlHelper,pathMatche,建立url和method的映射

public void afterPropertiesSet() {
		this.config = new RequestMappingInfo.BuilderConfiguration();
		this.config.setUrlPathHelper(getUrlPathHelper());
		this.config.setPathMatcher(getPathMatcher());
		this.config.setSuffixPatternMatch(this.useSuffixPatternMatch);
		this.config.setTrailingSlashMatch(this.useTrailingSlashMatch);
		this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch);
		this.config.setContentNegotiationManager(getContentNegotiationManager());		// 执行父类方法
		super.afterPropertiesSet();
	}

    public void afterPropertiesSet() {
		initHandlerMethods();
	}

2、initHandlerMethods

初始化HandlerMethod,建立url和method的映射

protected void initHandlerMethods() {
		// 获取当前spring所有Bean名称,处理所有候选Bean
		for (String beanName : getCandidateBeanNames()) {
			if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
				processCandidateBean(beanName);
			}
		}
	}

// 处理候选Bean
protected void processCandidateBean(String beanName) {
		Class<?> beanType = null;
		try {
		// 获取Handler类型
			beanType = obtainApplicationContext().getType(beanName);
		}
		catch (Throwable ex) {
			// An unresolvable bean type, probably from a lazy bean - let's ignore it.
			if (logger.isTraceEnabled()) {
				logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
			}
		}
		// 判断是否Handler
		if (beanType != null && isHandler(beanType)) {
			// 处理并映射HandlerMethods
			detectHandlerMethods(beanName);
		}
	}


// 判断是否Handler
	protected boolean isHandler(Class<?> beanType) {
	//判断是否有RequestMapping注解或者是否实现了Controller
		return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
				AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
	}

3、detectHandlerMethods

protected void detectHandlerMethods(Object handler) {
		// 获取Handler类型
		Class<?> handlerType = (handler instanceof String ?
				obtainApplicationContext().getType((String) handler) : handler.getClass());

		if (handlerType != null) {
		// 获取Handler真正的类型,存在被代理
			Class<?> userType = ClassUtils.getUserClass(handlerType);
			// 获取Handler中所有被@RequestMpping注解的方法
			Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
					(MethodIntrospector.MetadataLookup<T>) method -> {
						try {
							return getMappingForMethod(method, userType);
						}
						catch (Throwable ex) {
							throw new IllegalStateException("Invalid mapping on handler class [" +
									userType.getName() + "]: " + method, ex);
						}
					});
			if (logger.isTraceEnabled()) {
				logger.trace(formatMappings(userType, methods));
			}
			// 奖所有methods以HandlerMethod的方式注册到mappingRegistry中,
			// HandlerMethod = Handler + Method
			methods.forEach((method, mapping) -> {
				Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
				registerHandlerMethod(handler, invocableMethod, mapping);
			});
		}
	}

3、getHandlerInternal

获取HandlerMethod

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		// 获取截取host+contextPath后的url
		// 比如请求url: http://localhost/backend/login,context-path为/backend,则lookupPath=/login
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		// 放入request域
		request.setAttribute(LOOKUP_PATH, lookupPath);
		// 加读锁
		this.mappingRegistry.acquireReadLock();
		try {
		// 查找HandlerMethod,业务执行方法
			HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
			return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
		}
		finally {
		// 释放读锁
			this.mappingRegistry.releaseReadLock();
		}
	}

4、lookupHandlerMethod

查找HandlerMethod

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		// 获取截取host+contextPath后的url
		// 比如请求url: http://localhost/backend/login,context-path为/backend,则lookupPath=/login
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		// 放入request域
		request.setAttribute(LOOKUP_PATH, lookupPath);
		// 加读锁
		this.mappingRegistry.acquireReadLock();
		try {
		// 查找HandlerMethod,业务执行方法
			HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
			return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
		}
		finally {
		// 释放读锁
			this.mappingRegistry.releaseReadLock();
		}
	}

四、HttpRequestHandlerAdapter

执行器适配器

1、supports

判断是否该适配器适配

public boolean supports(Object handler) {
		return (handler instanceof HttpRequestHandler);
	}


2、handle

执行子类业务方法

public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return handleInternal(request, response, (HandlerMethod) handler);
	}

3、handleInternal

执行业务方法

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

		// 判断是否需要session锁进行同步处理
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					mav = invokeHandlerMethod(request, response, handlerMethod);
				}
			}
			else {
				// 执行业务方法
				mav = invokeHandlerMethod(request, response, handlerMethod);
			}
		}
		else {
			// 执行业务方法
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}

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

		return mav;
	}

3、invokeHandlerMethod

执行业务方法

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		try {
			// 将所有有@InitBinder注解的方法封装
			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
			// 将binderFactory和@ModelAndAttribute的封装起来
			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
			if (this.argumentResolvers != null) {
				invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
			}
			if (this.returnValueHandlers != null) {
				invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
			}
			invocableMethod.setDataBinderFactory(binderFactory);
			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
			// 执行@ModelAndAttribute的方法
			modelFactory.initModel(webRequest, mavContainer, invocableMethod);
			mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
            // 执行业务方法
			invocableMethod.invokeAndHandle(webRequest, mavContainer);
			if (asyncManager.isConcurrentHandlingStarted()) {
				return null;
			}

			// 获取ModelAndView
			return getModelAndView(mavContainer, modelFactory, webRequest);
		}
		finally {
			webRequest.requestCompleted();
		}
	}

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
        // 获取参数,执行业务方法
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
	    try {
	    	// ReturnValueHandler处理返回值
			this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}
		catch (Exception ex) {
			if (logger.isTraceEnabled()) {
				logger.trace(formatErrorForReturnValue(returnValue), ex);
			}
			throw ex;
		}
	}

// 获取ModelAndView
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
			ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

		modelFactory.updateModel(webRequest, mavContainer);
		// 如果已经被ReturnValueHandler处理过的,不需要由SpringMVC处理了
		if (mavContainer.isRequestHandled()) {
			return null;
		}
		ModelMap model = mavContainer.getModel();
		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;
	}

办公设备租赁,深圳惠源.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值