栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringMVC 执行流程源码解析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringMVC 执行流程源码解析

文章目录
  • 前言
  • 一、DispatcherServlet
      • 1、doServcie
      • 2、doDispatch
      • 3、getHandler
      • 3、getHandlerAdapter
  • 二、AbstractHandlerMapping
      • 1、getHandler
  • 三、RequestMappingHandlerMapping
      • 1、afterPropertiesSet
      • 2、initHandlerMethods
      • 3、detectHandlerMethods
      • 3、getHandlerInternal
      • 4、lookupHandlerMethod
  • 四、HttpRequestHandlerAdapter
      • 1、supports
  • 总结

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

前言

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拦截器得前置方法
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// 执行handler业务方法
				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;
	}
3、getHandlerAdapter

获取处理器适配器,由于Handler,可能是Controller,也可能是Method,所以需要适配器进行适配。

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");
	}
二、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 methods = MethodIntrospector.selectMethods(userType,
					(MethodIntrospector.metadataLookup) 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);
	}


总结

如果需要自己实现一个Starter
那只需要meta-INF/spring-autoconfigure-metadata.properties的资源,并org.springframework.boot.autoconfigure.EnableAutoConfiguration的值为自己写的Configuration即可,一般框架会区分start包和真正实现的jar,然后由start包依赖真正实现的jar包

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/673325.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号