转载

springMVC源码分析

常见以web.xml配置方式

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         id="WebApp_ID" version="3.0">
    <display-name>CtrTimeOut</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <context-param>
        <param-name>contextConfigLocation</param-name>
      	# spring的配置
        <param-value>classpath:config/spring/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>controller</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
          	# springmvc的配置
            <param-value>classpath:config/spring/spring-controller.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>controller</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

ContextLoadListener创建WebApplicationContext作为spring的容器上下文

#org.springframework.web.context.ContextLoader
	/**
	 * 根据xml配置创建applicationContext
	 */
	public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
		...
		try {
			// Store context in local instance variable, to guarantee that
			// it is available on ServletContext shutdown.
			if (this.context == null) {//判空 (以注解方式配置时非空)
				this.context = createWebApplicationContext(servletContext);
			}
			if (this.context instanceof ConfigurableWebApplicationContext) {
				ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
				if (!cwac.isActive()) {
					...
					//读取contextConfigLocation配置并refresh()
					configureAndRefreshWebApplicationContext(cwac, servletContext);
				}
			}
//将applicationContext设置到servletContext中
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
			...
			return this.context;
		}
	}

DispatcherServlet创建WebApplicationContext作为springmvc的上下文 并将ContextLoadListener创建的上下文设置为自身的parent

DispatcherServlet extends FrameworkServlet 
#org.springframework.web.servlet.FrameworkServlet
	@Override
	protected final void initServletBean() throws ServletException {
		...
		try {
			this.webApplicationContext = initWebApplicationContext();
			initFrameworkServlet();
		}
		...
	}
	protected WebApplicationContext initWebApplicationContext() {
		WebApplicationContext rootContext =
				WebApplicationContextUtils.getWebApplicationContext(getServletContext());
		WebApplicationContext wac = null;
		...
		if (wac == null) {
			//创建applicationContext
			wac = createWebApplicationContext(rootContext);
		}
		...
		return wac;
	}
	protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
		//XmlWebApplicationContext 
		Class<?> contextClass = getContextClass();
		...
		//创建applicationContext
		ConfigurableWebApplicationContext wac =
				(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
		wac.setEnvironment(getEnvironment());
		//设置parent(ContextLoadListener中创建的applicationContext)
		wac.setParent(parent);
		//读取contextConfigLocation配置
		wac.setConfigLocation(getContextConfigLocation());
		//refresh()
		configureAndRefreshWebApplicationContext(wac);
		return wac;
	}

springmvc的applicationContext会去读取配置文件 我们来看一个最简单的配置文件

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
      http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd" 
      default-autowire="byName">
   #springmvc容器扫描路径
   <context:component-scan base-package="com.iflytek.ossp.ctrtimeout.controller"></context:component-scan>
   #spring4新增的标签 主要是添加了默认的HandleMappin,ViewResolver,HandleAdapter
   <mvc:annotation-driven />
</beans>

springMvc配置解析

根据spring的自定义schema解析机制 我们找到 在下图位置

http/://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
springMVC源码分析

可以看到mvc所有的标签解析器都定义在此

public class MvcNamespaceHandler extends NamespaceHandlerSupport {
	@Override
	public void init() {
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
		registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
		registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
		registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
		registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
		registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
		registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
		registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
		registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
		registerBeanDefinitionParser("velocity-configurer", new VelocityConfigurerBeanDefinitionParser());
		registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
	}
}

来看一下AnnotationDrivenBeanDefinitionParser解析器做了什么

解析过程较为复杂 通过注释我们可以得知以下对象将被装载

springMVC源码分析

DispatcherServlet调用过程

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		...
		try {
			ModelAndView mv = null;
			Exception dispatchException = null;
			try {
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);
				//1.调用handlerMapping获取handlerChain
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}
				// 2.获取支持该handler解析的HandlerAdapter
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
				...
				// 3.使用HandlerAdapter完成handler处理
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}
				// 4.视图处理(页面渲染)
				applyDefaultViewName(request, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		...
	}

过程概括:

  1. 调用HandleMapping得到handler
  2. 调用HandleAdapter执行handle过程(参数解析 过程调用)
  3. 调用ViewResolver进行视图解析
  4. 渲染视图
springMVC源码分析
上述图片来自网络

HandleMapping

定义: 请求路径-处理过程映射管理

打个比方就是根据你的http请求的路径得到可以处理的handler(你的Controller方法)

/**
 * Interface to be implemented by objects that define a mapping between
 * requests and handler objects.
 */
public interface HandlerMapping {
  //根据request获取处理链
   HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}

以RequestMappingHandlerMapping为例 我们先看下他的继承关系

springMVC源码分析

可以看到有个InitlizingBean(spring的生命周期接口)我们就由他入手

#org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
	//1.
    @Override
    public void afterPropertiesSet() {
       if (this.useRegisteredSuffixPatternMatch) {
          this.fileExtensions.addAll(this.contentNegotiationManager.getAllFileExtensions());
       }
       super.afterPropertiesSet();
    }
    //4.
	@Override
	protected boolean isHandler(Class<?> beanType) {
		return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) ||
				(AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null));
	}
	//6.
	@Override
	protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
		RequestMappingInfo info = null;
		RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);
		if (methodAnnotation != null) {
			//组装映射信息
			RequestCondition<?> methodCondition = getCustomMethodCondition(method);
			info = createRequestMappingInfo(methodAnnotation, methodCondition);
			RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
			if (typeAnnotation != null) {
				RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);
				info = createRequestMappingInfo(typeAnnotation, typeCondition).combine(info);
			}
		}
		return info;
	}
#org.springframework.web.servlet.handler.AbstractHandlerMethodMapping
	//2.
    @Override
    public void afterPropertiesSet() {
    	initHandlerMethods();
    }
	/**
	 * Scan beans in the ApplicationContext, detect and register handler methods.
	 * @see #isHandler(Class)
	 * @see #getMappingForMethod(Method, Class)
	 * @see #handlerMethodsInitialized(Map)
	 */
	 //3.
	protected void initHandlerMethods() {
		if (logger.isDebugEnabled()) {
			logger.debug("Looking for request mappings in application context: " + getApplicationContext());
		}
		//从容器中获取所有object类型名
		String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
				BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
				getApplicationContext().getBeanNamesForType(Object.class));
		for (String beanName : beanNames) {
			//抽象,过滤(在RequestMappingHandlerMapping中根据Controller和RequestMapping注解过滤)
			if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX) &&
					isHandler(getApplicationContext().getType(beanName))){
				//探测类中定义的handler方法
				detectHandlerMethods(beanName);
			}
		}
		handlerMethodsInitialized(getHandlerMethods());
	}
	//5.
	protected void detectHandlerMethods(final Object handler) {
		Class<?> handlerType =
				(handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass());
		final Map<Method, T> mappings = new IdentityHashMap<Method, T>();
		final Class<?> userType = ClassUtils.getUserClass(handlerType);
		//得到符合条件的handler方法
		Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() {
			@Override
			public boolean matches(Method method) {
				//抽象,得到映射信息(如RequestMappingInfo)
				T mapping = getMappingForMethod(method, userType);
				if (mapping != null) {
					mappings.put(method, mapping);
					return true;
				}
				else {
					return false;
				}
			}
		});
		//注册handler方法
		for (Method method : methods) {
			registerHandlerMethod(handler, method, mappings.get(method));
		}
	}

上述代码就是HandlerMapping初始化映射关系的代码

过程概括:

  1. 获取所有object子类
  2. 根据条件过滤出handle处理类
  3. 解析handle类中定义的处理方法
  4. 保存解析得出的映射关系

来看一下getHandler(Request)的方法实现,看看DispatcherServlet是如何得到处理链的

#org.springframework.web.servlet.handler.AbstractHandlerMapping
@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  //抽象,调用子类实现得到一个handler(可以是任一对象,需要通过HandleAdapter来解析)
  //RequestMappingInfoHandlerMapping中具体实现就是匹配请求路径和RequestMapping注解
   Object handler = getHandlerInternal(request);
   ...
  //包装handle成HandlerExecutionChain
   return getHandlerExecutionChain(handler, request);
}

HandleAdapter

定义: 根据HandlerMapping.getHandler()得到的Handler信息,对http请求参数解析并绑定

先看一下HandlerAdapter的接口定义

public interface HandlerAdapter {
   //判断是否支持该handler类型的解析
   boolean supports(Object handler);
   //参数解析 并调用handler完成过程调用 
   ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
   //用于处理http请求头中的last-modified
   long getLastModified(HttpServletRequest request, Object handler);

}

以RequestMappingHandlerAdapter为例来讲,先看下继承关系

springMVC源码分析

同样看到了实现了InitializingBean接口 从这入手

#org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
  @Override
  public void afterPropertiesSet() {
     // 1.初始化ControllerAdvice注解的对象
     initControllerAdviceCache();
	// 2.装载ArgumentResolver(默认+自定义)
     if (this.argumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
        //包装成一个Composite对象
        this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
     }
     // 2.装载InitBinderArgumentResolvers(默认+自定义)
     if (this.initBinderArgumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
        //包装成一个Composite对象
        this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
     }
     // 3.装载ReturnValueHandlers(默认+自定义)
     if (this.returnValueHandlers == null) {
        List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
        //包装成一个Composite对象
        this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
     }
  }
	private void initControllerAdviceCache() {
		//从容器中获取所有带有ControllerAdvices注解的类名 并包装成ControllerAdviceBean
		List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
		OrderComparator.sort(beans);
		List<Object> responseBodyAdviceBeans = new ArrayList<Object>();
		for (ControllerAdviceBean bean : beans) {
			//筛选出带有ModelAttribute且不带RequestMapping注解的方法
			Set<Method> attrMethods = HandlerMethodSelector.selectMethods(bean.getBeanType(), MODEL_ATTRIBUTE_METHODS);
			if (!attrMethods.isEmpty()) {
				//保存到map中
				this.modelAttributeAdviceCache.put(bean, attrMethods);
			}
			//筛选出带InitBinder注解的方法
			Set<Method> binderMethods = HandlerMethodSelector.selectMethods(bean.getBeanType(), INIT_BINDER_METHODS);
			if (!binderMethods.isEmpty()) {
            	//保存到map中
				this.initBinderAdviceCache.put(bean, binderMethods);
			}
			//如果该类同时实现了ResponseBodyAdvice接口 添加到结合中
			if (ResponseBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {
				responseBodyAdviceBeans.add(bean);
			}
		}
		//保存到全局变量中
		if (!responseBodyAdviceBeans.isEmpty()) {
			this.responseBodyAdvice.addAll(0, responseBodyAdviceBeans);
		}
	}

过程概括:

  1. 装载带有ControllerAdvices注解的对象
  2. 装载ArgumentResolvers(默认+自定义)
  3. 装载InitBinderArgumentResolvers(默认+自定义)
  4. 装载ReturnValueHandlers(默认+自定义)

自定义拓展方式放后面说

以下为HandlerAdapter默认解析器

springMVC源码分析

看一下 HandlerMethodReturnValueHandler 接口和HandlerMethodArgumentResolver接口

//参数解析器
public interface HandlerMethodArgumentResolver {
  //判断是否支持该参数的解析(根据类型,注解等)
   boolean supportsParameter(MethodParameter parameter);
  //对参数进行解析 得到解析结果
   Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
         NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;
}
//返回值解析器
public interface HandlerMethodReturnValueHandler {
  //判断是否支持该返回值的解析(根据类型,注解等)
	boolean supportsReturnType(MethodParameter returnType);
  //对返回值进行解析
	void handleReturnValue(Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
}

上述即HandlerAdapter的初始化过程

DispatcherServlet调用HandlerAdapter过程

//1.调用support()方法判断是否支持改handler的解析
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 如果是Get或Head请求 调用getLastModified()获取上次更新时间 
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());

DisPatcherServlet调用HandlerAdapter分为三步:

  1. 调用support()方法判断是否支持改handler的解析
#org.springframework.web.servlet.DispatcherServlet
//在doDispatch()方法中调用了getHandlerAdapter(Object)方法来得到一个HandlerAdapter
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        //调用HandlerAdapter.support()方法 判断是否支持该handler对象的解析
       for (HandlerAdapter ha : this.handlerAdapters) {
            ...
          if (ha.supports(handler)) {
             return ha;
          }
       }
      ...
    }
#org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter
	@Override
	public final boolean supports(Object handler) {
		return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
	}
#org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
	@Override
	protected boolean supportsInternal(HandlerMethod handlerMethod) {
		return true;
	}
  1. 如果是Get或Head请求 调用getLastModified()获取上次更新时间

如果小于浏览器缓存更新时间 则直接返回 浏览器使用本地缓存

#org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
@Override
protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) {
   return -1;
}
  1. 调用handler()方法完成过程调用(参数解析 返回值解析)
#org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter
    @Override
    public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
          throws Exception {
       return handleInternal(request, response, (HandlerMethod) handler);
    }

#org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
	@Override
	protected ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
		//对http协议缓存方面的请求头的处理(expire,cache-control)
		if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
			// Always prevent caching in case of session attribute management.
			checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
		}
		else {
			// Uses configured default cacheSeconds setting.
			checkAndPrepare(request, response, true);
		}
		// Execute invokeHandlerMethod in synchronized block if required.
		if (this.synchronizeOnSession) {//是否使用session锁
			HttpSession session = request.getSession(false);
			if (session != null) {
              	//得到互斥量
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {//执行过程调用
					return invokeHandleMethod(request, response, handlerMethod);
				}
			}
		}
		//执行过程调用
		return invokeHandleMethod(request, response, handlerMethod);
	}
	//根据HandlerMethod解析参数 并完成过程调用得到一个ModelAndView
	private ModelAndView invokeHandleMethod(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
		ServletWebRequest webRequest = new ServletWebRequest(request, response);
		//使用initBinderAdviceCache对@initBinder进行处理
		WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        // 使用modelAttributeAdviceCache对@ModelAttribute进行处理
		ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
		ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);
		ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
		modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);		mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
		//对异步的处理 暂时不管 TODO后面再分析
      	...
      	//1 完成过程调用
		requestMappingMethod.invokeAndHandle(webRequest, mavContainer);
		if (asyncManager.isConcurrentHandlingStarted()) {
			return null;
		}
		//2 包装ModelAndView
		return getModelAndView(mavContainer, modelFactory, webRequest);
	}

handle()过程总结:

  1. 执行过程调用requestMappingMethod.invokeAndHandle(webRequest, mavContainer);
#org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod
        public void invokeAndHandle(ServletWebRequest webRequest,
                                    ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
      // 1.1 参数解析 并完成过程调用
      Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
      setResponseStatus(webRequest);
      ...
        try {
          //1.2 使用returnValueHandlers对返回结果进行处理 讲结果塞到mavContainer中 过程类似参数解析
          this.returnValueHandlers.handleReturnValue(
            returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
        }
    }
#org.springframework.web.method.support.InvocableHandlerMethod
        public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
                                       Object... providedArgs) throws Exception {
      //1.1.1 参数解析并得到绑定的结果
      Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
      ...
        //1.1.2 反射完成过程调用 
        Object returnValue = doInvoke(args);
      ...
        return returnValue;
    }
    private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
                                             Object... providedArgs) throws Exception {
      //参数信息
      MethodParameter[] parameters = getMethodParameters();
      Object[] args = new Object[parameters.length];
      for (int i = 0; i < parameters.length; i++) {
        //调用HandlerMethodArgumentResolver#supportsParameter判断是否支持
        if (this.argumentResolvers.supportsParameter(parameter)) {
          try {
            //调用HandlerMethodArgumentResolver#resolveArgument进行解析
            args[i] = this.argumentResolvers.resolveArgument(
              parameter, mavContainer, request, this.dataBinderFactory);
            continue;
          }
          ...
        }
        ...
      }
      return args;
    }
  1. 包装ModelAndView getModelAndView(mavContainer, modelFactory, webRequest);
//从mavContainer取出结果 包装成ModelAndView
	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 mav = new ModelAndView(mavContainer.getViewName(), model);
      if (!mavContainer.isViewReference()) {
        mav.setView((View) mavContainer.getView());
      }
      //如果是redirect请求
      if (model instanceof RedirectAttributes) {
        Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
      }
      return mav;
    }

到此 HandlerAdapter的调用过程算分析完了

springMVC思维导图

原文  https://juejin.im/post/5aaf4c556fb9a028b547af83
正文到此结束
Loading...