springmvc工作原理和源码级别解析

(1)客户端(浏览器)发送请求,直接请求到DispatcherServlet。

(2)DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler。

(3)解析到对应的Handler后,开始由HandlerAdapter适配器处理。

(4)HandlerAdapter会根据Handler来调用真正的处理器开处理请求,并处理相应的业务逻辑。

(5)处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是个逻辑上的View。

(6)ViewResolver会根据逻辑View查找实际的View。

(7)DispaterServlet把返回的Model传给View。

(8)通过View返回给请求者(浏览器)

springmvc入口 

1、Spring 容器初始化bean时会回调afterPropertiesSet(),实现获取通过适配HandlerMapping适配到对应的HandlerMappingAdapter。

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
==>

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean

==>
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

==>
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean

==>
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods

 protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {


  boolean isInitializingBean = (bean instanceof InitializingBean);

  if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {

   if (logger.isTraceEnabled()) {

    logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");

   }

   if (System.getSecurityManager() != null) {

    try {

     AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {

      ((InitializingBean) bean).afterPropertiesSet();

      return null;

     }, getAccessControlContext());

    }

    catch (PrivilegedActionException pae) {

     throw pae.getException();

    }

   }

   else {

    ((InitializingBean) bean).afterPropertiesSet();

   }

  }



  if (mbd != null && bean.getClass() != NullBean.class) {

   String initMethodName = mbd.getInitMethodName();

   if (StringUtils.hasLength(initMethodName) &&

     !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&

     !mbd.isExternallyManagedInitMethod(initMethodName)) {

    invokeCustomInitMethod(beanName, bean, mbd);

   }

  }

 }

2、预加载RequestMappingHandlerMapping类。该类负责将@RequestMapping的信息RequestMappingInfo信息和HanlderMethod信息到内存中

2-1、静态模块预加载文件DispatcherServlet.properties获取预加载的RequestMappingHandlerMapping类。

/**

 * Name of the class path resource (relative to the DispatcherServlet class)

 * that defines DispatcherServlet's default strategy names.

 */

private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";

static {

   // Load default strategy implementations from properties file.

   // This is currently strictly internal and not meant to be customized

   // by application developers.

   try {

      ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);

      defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);

   }

   catch (IOException ex) {

      throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());

   }

}

2-2、初始化RequestMappingInfo(@RequestMapping注解的信息)

 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#createRequestMappingInfo

组装 RequestMappingInfo 模板(存储了控制层接口方法的url,请求方法,参数,请求头,接口consumes(处理请求的提交类型 content-type)接口的produces(指定接口的返回值类型))

2-3、初始化HandlerMethod(@RequestMapping注释的具体方法信息)

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#afterPropertiesSet

 afterPropertiesSet具体过程:

判断该bean的类型是不是标有@Controller、@RequestMapping注解的类(isHandler)。

如果是就通过aop获取标有@RequestMapping方法的具体的method信息(detectHandlerMethods),

并且将RequestMappingInfo 信息与HandlerMethod绑定起来,存入内存中。(register)

org.springframework.web.servlet.mvc.method.annotation#isHandler

org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#detectHandlerMethods

org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#register

3、预加载RequestMappingHandlerAdapter适配器(web九大组件之中最重要的组件),提供数据绑定、数据转换、数据校验、内容协商。

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#afterPropertiesSet

 3-1、缓存@ControllerAdvice注解和@RestControllerAdvice的bean,缓存@ModelAttribute的bean和方法、缓存@InitBinder的bean和方法、缓存RequestBodyAdvice/ResponseBodyAdvice接口实现的Bean。

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#initControllerAdviceCache

3-2、初始化入参、InitBinder、返回参数解析器,并且和bean绑定。

入参解析器集合:

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getDefaultArgumentResolvers

@InitBinder解析器集合

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getDefaultInitBinderArgumentResolvers

返回参数解析器集合

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getDefaultReturnValueHandlers

各种解析器集合提供了可以根据基于注解、参数类型、用户自定义、默认参数解析器

@Nullable
private List<HandlerMethodArgumentResolver> customArgumentResolvers;

@Nullable
private HandlerMethodArgumentResolverComposite argumentResolvers;

@Nullable
private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;

@Nullable
private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;

@Nullable
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;

@Override
public void afterPropertiesSet() {
	// Do this first, it may add ResponseBody advice beans
        
	initControllerAdviceCache();
      
	if (this.argumentResolvers == null) {
		List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
		this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
	}
	if (this.initBinderArgumentResolvers == null) {
		List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
		this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
	}
	if (this.returnValueHandlers == null) {
		List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
		this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
	}
}

4、请求处理

org.springframework.web.servlet.DispatcherServlet#doDispatch

 关键过程:

4-1、检查是否是上传请求

org.springframework.web.servlet.DispatcherServlet#checkMultipart

4-2、适配HandlerMapping(RequestMappingHandlerMapping

前提:

spring初始化bean回调方法时候,缓存了全部的HandlerMapping。

适配过程:

根据请求找到对应的MappingRegisty和HandlerIntercepter。类、方法、拦截器、cors信息,只是实例化,并未初始化。并且存入HandlerExecutionChain的链路中。

org.springframework.web.servlet.DispatcherServlet#getHandler

4-3、根据handler适配Adapter(RequestMappingHandlerAdapter

org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter

4-4、Adapter处理:解析方法入参、出参,并且赋值,并且和ModelAndView绑定,如果没又和ModelAndView绑定,那么直接返回null。

 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal

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

				// Determine handler for the current request.
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
				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 (logger.isDebugEnabled()) {
						logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// Actually invoke the handler.
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

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

				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);
			}
			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);
				}
			}
		}
	}
  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值