SpringMVC源码(八):Controller控制器执行流程

  在MVC请求流程中,获取到HandlerAdapter适配器后,会执行handler处理器(Controller控制器)的相关逻辑,通过适配器的handle()方法,完成目标Controller处理器的调用。源码(七):HandlerAdapter适配器获取中提到,以HandlerAdapter为RequestMappingHandlerAdapter类型的为例,执行handler处理器(Controller控制器)的相关处理。

1、核心流程图

  HandlerAdapter处理器适配器调用目标Controller控制器的方法逻辑的核心流程图:

  

2、核心流程源码分析

  AbstractHandlerMethodAdapter#handle() 核心伪代码

1 // 处理目标handler处理器中的逻辑
2 public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
3       throws Exception {
4 
5    return handleInternal(request, response, (HandlerMethod) handler);
6 }

  RequestMappingHandlerAdapter#handleInternal 核心伪代码

1 protected ModelAndView handleInternal(HttpServletRequest request,
2       HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
3    
4    // 执行Controller控制器的目标方法
5    ModelAndView mav = invokeHandlerMethod(request, response, handlerMethod);
6 
7    // 返回执行结果ModeAndView
8    return mav;
9 }

   RequestMappingHandlerAdapter#invokeHandlerMethod 核心伪代码

 1 // 调用处理器的目标方法
 2 protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
 3       HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
 4 
 5    // 使用request和response创建ServletWebRequest对象
 6    ServletWebRequest webRequest = new ServletWebRequest(request, response);
 7    try {
 8       // 创建WebDataBinderFactory对象,此对象用来创建WebDataBinder对象,进行参数绑定,
 9       WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
10       
11       // 创建ModelFactory对象,此对象主要用来处理model
12       // 主要是两个功能,1是在处理器具体处理之前对model进行初始化,2是在处理完请求后对model参数进行更新
13       ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
14 
15       // 创建ServletInvocableHandlerMethod对象,并设置其相关属性,实际的请求处理就是通过此对象来完成的,参数绑定、处理请求以及返回值处理都在此处完成
16       ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
17       // 设置参数处理器
18       if (this.argumentResolvers != null) {
19          invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
20       }
21       // 设置返回值处理器
22       if (this.returnValueHandlers != null) {
23          invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
24       }
25       // 设置参数绑定工厂对象
26       invocableMethod.setDataBinderFactory(binderFactory);
27       // 设置参数名称发现器
28       invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
29 
30       // 创建ModelAndViewContainer对象,用于保存model和View对象
31       ModelAndViewContainer mavContainer = new ModelAndViewContainer();
32       // 将flashmap中的数据设置到model中
33       mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
34       // 使用modelFactory将sessionAttributes和注释了@ModelAttribute的方法的参数设置到model中
35       modelFactory.initModel(webRequest, mavContainer, invocableMethod);
36       // 根据配置对ignoreDefaultModelOnRedirect进行设置
37       mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
38 
39       // 创建AsyncWebRequest异步请求对象
40       AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
41       asyncWebRequest.setTimeout(this.asyncRequestTimeout);
42 
43       // 创建WebAsyncManager异步请求管理器对象
44       WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
45       asyncManager.setTaskExecutor(this.taskExecutor);
46       asyncManager.setAsyncWebRequest(asyncWebRequest);
47       asyncManager.registerCallableInterceptors(this.callableInterceptors);
48       asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
49 
50       // 如果当前异步请求已经处理并得到结果,则将返回的结果放到mavContainer对象中,然后将invocable对象进行包装转换,转成需要的执行对象然后开始执行
51       if (asyncManager.hasConcurrentResult()) {
52          Object result = asyncManager.getConcurrentResult();
53          mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
54          asyncManager.clearConcurrentResult();
55          LogFormatUtils.traceDebug(logger, traceOn -> {
56             String formatted = LogFormatUtils.formatValue(result, !traceOn);
57             return "Resume with async result [" + formatted + "]";
58          });
59          // 转换具体的invocable执行对象
60          invocableMethod = invocableMethod.wrapConcurrentResult(result);
61       }
62 
63       // 执行调用
64       invocableMethod.invokeAndHandle(webRequest, mavContainer);
65       if (asyncManager.isConcurrentHandlingStarted()) {
66          return null;
67       }
68 
69       // 处理完请求后的后置处理
70       // 1、调用ModelFactory的updateModel方法更新model,包括设置SessionAttribute和给Model设置BinderResult
71       // 2、根据mavContainer创建了ModelAndView
72       // 3、如果mavContainer里的model是RedirectAttributes类型,则将其设置到FlashMap
73       return getModelAndView(mavContainer, modelFactory, webRequest);
74    }
75    finally {
76       // 标记请求完成
77       webRequest.requestCompleted();
78    }
79 }

1、根据request、response创建ServletWebRequest对象

2、创建WebDataBinderFactory对象

  创建WebDataBinderFactory对象,用于处理@InitBinder注解修饰的方法。

  RequestMappingHandlerAdapter#getDataBinderFactory() 核心伪代码

 1 // @InitBinder修饰方法缓存
 2 private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64);
 3 
 4 // @InitBinder修饰方法过滤器
 5 public static final MethodFilter INIT_BINDER_METHODS = method ->
 6       AnnotatedElementUtils.hasAnnotation(method, InitBinder.class);
 7 
 8 private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
 9    // 获取当前handler的Class对象(Controller控制器的Class对象)
10    Class<?> handlerType = handlerMethod.getBeanType();
11    // 检查当前Handler中的initBinder方法是否已经存在于缓存中
12    Set<Method> methods = this.initBinderCache.get(handlerType);
13    // 如果没有找到则查找并设置到缓冲中
14    if (methods == null) {
15       // 将当前Controller中所有被@InitBinder注解修饰的方法都获取到
16       methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
17       this.initBinderCache.put(handlerType, methods);
18    }
19    // 定义保存InitBinder方法的变量
20    List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();
21    // 将所有符合条件的全局InitBinder方法添加到initBinderMethods
22    // 获取@ControllerAdvice注解修饰的类中被@InitBinder注解修饰的方法
23    this.initBinderAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
24       if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
25          Object bean = controllerAdviceBean.resolveBean();
26          for (Method method : methodSet) {
27             initBinderMethods.add(createInitBinderMethod(bean, method));
28          }
29       }
30    });
31    // 将当前handler中的initBinder方法添加到initBinderMethods
32    for (Method method : methods) {
33       // 创建当前方法对应的bean对象
34       Object bean = handlerMethod.getBean();
35       // 将method适配为可执行的invocableHandlerMethod
36       initBinderMethods.add(createInitBinderMethod(bean, method));
37    }
38    // 创建DataBinderFactory并返回
39    return createDataBinderFactory(initBinderMethods);
40 }

  1、获取当前Controller中被@InitBinder修饰的方法。优先从initBinderCache缓存中获取,若缓存中不存在,则在当前Controller中查询,并将查询到的结果保存在methods集合中,并设置进initBinderCache缓存中。

  2、获取全局(被@ControllerAdvice注解修饰的类)被@InitBinder注解修饰的方法,并将目标方法用InvocableHandlerMethod类型的对象封装,保存在initBinderMethods集合中。

  3、遍历Controller中被被@InitBinder修饰的方法集合methods,将目标方法用InvocableHandlerMethod类型的对象封装,添加进initBinderMethods集合中。

  4、创建WebDataBinderFactory类型的对象,将initBinderMethods集合设置到InitBinderDataBinderFactory的binderMethods属性中,返回WebDataBinderFactory类型的对象。

3、创建ModelFactory对象

  创建WebDataBinderFactory对象,用于处理@ModelAttribute注解修饰的方法。RequestMappingHandlerAdapter#getModelFactory() 核心伪代码

 1 // 被@ModelAttribute注解修饰的方法缓存
 2 private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<>(64);
 3 
 4 // 被@ModelAttribute修饰,未被@RequestMapping修饰的方法过滤器
 5 public static final MethodFilter MODEL_ATTRIBUTE_METHODS = method ->
 6       (!AnnotatedElementUtils.hasAnnotation(method, RequestMapping.class) &&
 7             AnnotatedElementUtils.hasAnnotation(method, ModelAttribute.class));
 8 
 9 // 被@ContollerAdvice注解修饰的类中,ModelAttribute方法
10 private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache = new LinkedHashMap<>();
11 
12 // 获取ModelFactory对象
13 private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
14     // 获取sessionAttributesHandler
15     SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
16     // 获取处理器类的类型
17     Class<?> handlerType = handlerMethod.getBeanType();
18     // 从缓存中获取处理器类中注释了@ModelAttribute而且没有注释@RequestMapping的类
19     Set<Method> methods = this.modelAttributeCache.get(handlerType);
20     // 缓存中不存在
21     if (methods == null) {     
22         // 从当前Controller中获取被@ModelAttribute注解修饰,未被@RequestMapping注解修饰的方法
23         methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
24         // 将方法设置进modelAttributeCache缓存中
25         this.modelAttributeCache.put(handlerType, methods);
26     }
27     // 定义保存ModelAttribute方法的变量
28    
29     List<InvocableHandlerMethod> attrMethods = new ArrayList<>();
30         
31     // 先添加全局@ControllerAdvice的@ModelAttribute方法
32     this.modelAttributeAdviceCache.forEach((controllerAdviceBean, methodSet) -> {        
33         if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
34             Object bean = controllerAdviceBean.resolveBean();
35             // 将ModelAttribut方法用InvocableHandlerMethod类型对象封装,并添加进attrMethods中
36             for (Method method : methodSet) {
37             attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
38             }
39         }
40     });
41     // 再添加当前处理器Controller定义的@ModelAttribute方法
42     for (Method method : methods) {
43         Object bean = handlerMethod.getBean();
44         attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
45     }
46     // 新建ModelFactory对象
47     // 此处需要三个参数,第一个是被@ModelAttribute的方法,第二个是WebDataBinderFactory,第三个是SessionAttributeHandler
48     return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
49 }

  1、获取当前Controller中被@ModelAttribute修饰,未被@RequestMapping修饰的方法。优先从modelAttributeCache缓存中获取,若缓存中不存在,则在当前Controller中查询,并将查询到的结果保存在methods集合中,并设置进modelAttributeCache缓存中。

  2、获取全局(被@ControllerAdvice注解修饰的类)被@ModelAttribute注解修饰的方法,并将目标方法用InvocableHandlerMethod类型的对象封装,保存在attrMethods集合中。

  3、遍历Controller中被@ModelAttribute修饰的方法集合methods,将目标方法用InvocableHandlerMethod类型的对象封装,添加进attrMethods集合中。

  4、创建ModelFactory类型的对象,将attrMethods集合设置到ModeFaactory的modelMethods属性中,返回ModeFaactory类型的对象。

4、创建ServletInvocableHandlerMethod对象并完成属性设置

  创建ServletInvocableHandlerMethod对象,用于调用Controller控制器中的目标方法逻辑。

4.1、创建ServletInvocableHandlerMethod对象

  RequestMappingHandlerAdapter#createInvocableHandlerMethod() 核心伪代码

1 // 创建ServletInvocableHandlerMethod对象包装handlerMethod
2 protected ServletInvocableHandlerMethod createInvocableHandlerMethod(HandlerMethod handlerMethod) {
3    return new ServletInvocableHandlerMethod(handlerMethod);
4 }

4.2、属性设置

 1 // 设置参数处理器
 2 if (this.argumentResolvers != null) {
 3    invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
 4 }
 5 // 设置返回值处理器
 6 if (this.returnValueHandlers != null) {
 7    invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
 8 }
 9 // 设置参数绑定工厂对象
10 invocableMethod.setDataBinderFactory(binderFactory);
11 // 设置参数名称发现器
12 invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

1、属性初始化

  参数解析器argumentResolvers、返回值处理器returnValueHandlers的初始化过程与源码(六):Handler处理器获取中AbstractHandlerMethodMapping#mappingRegistry属性的初始化过程类似。

  在MVC容器启动,创建MVC容器中单例的bean对象,创建RequestMappingHandlerAdapter的bean实例过程中,在getBean() -> doGetBean() -> createBean() -> doCreateBean() -> initializeBean() -> invokeInitMethods() -> RequestMappingHandlerAdapter#afterPropertiesSet()。

  RequestMappingHandlerAdapter#afterPropertiesSet(),调用bean的afterPropertiesSet方法。

 1 public void afterPropertiesSet() {
 2    // 初始化ControllerAdvice缓存 
 3    initControllerAdviceCache();
 4    // 初始化参数处理器 - argumentResolvers
 5    if (this.argumentResolvers == null) {
 6       // 获取默认的参数处理器
 7       List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
 8       this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
 9    }
10    // 初始化InitBinder方法参数处理器 - initBinderArgumentResolvers
11    if (this.initBinderArgumentResolvers == null) {
12        // 获取默认的InitBinder方法参数处理器
13       List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
14       this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
15    }
16    // 初始化返回值处理器 - returnValueHandlers
17    if (this.returnValueHandlers == null) {
18       // 获取默认的返回值处理器
19       List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
20       this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
21    }
22 }
1.1、参数处理器

  初始化参数值处理器,,并将获取到的参数值处理器设置进HandlerMethodArgumentResolverComposite的argumentResolvers属性中,MVC容器中实现的默认参数值处理器如下:

获取默认返回值处理器器 RequestMappingHandlerAdapter#getDefaultArgumentResolvers() 核心伪代码

 1 private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
 2    List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(30);
 3 
 4    // 基于注解的参数处理器
 5    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
 6    resolvers.add(new RequestParamMapMethodArgumentResolver());
 7    resolvers.add(new PathVariableMethodArgumentResolver());
 8    resolvers.add(new PathVariableMapMethodArgumentResolver());
 9    resolvers.add(new MatrixVariableMethodArgumentResolver());
10    resolvers.add(new MatrixVariableMapMethodArgumentResolver());
11    resolvers.add(new ServletModelAttributeMethodProcessor(false));
12    resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
13    resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
14    resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
15    resolvers.add(new RequestHeaderMapMethodArgumentResolver());
16    resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
17    resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
18    resolvers.add(new SessionAttributeMethodArgumentResolver());
19    resolvers.add(new RequestAttributeMethodArgumentResolver());
20 
21    // 基于类型的参数处理器
22    resolvers.add(new ServletRequestMethodArgumentResolver());
23    resolvers.add(new ServletResponseMethodArgumentResolver());
24    resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
25    resolvers.add(new RedirectAttributesMethodArgumentResolver());
26    resolvers.add(new ModelMethodProcessor());
27    resolvers.add(new MapMethodProcessor());
28    resolvers.add(new ErrorsMethodArgumentResolver());
29    resolvers.add(new SessionStatusMethodArgumentResolver());
30    resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
31 
32    // 自定义参数解析器
33    if (getCustomArgumentResolvers() != null) {
34       resolvers.addAll(getCustomArgumentResolvers());
35    }
36 
37    // Catch-all
38    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
39    resolvers.add(new ServletModelAttributeMethodProcessor(true));
40 
41    return resolvers;
42 }

  参数处理器的顶级接口HandlerMethodArgumentResolver包含两个核心方法:supportsParameter()、resolveArgument()

  supportsParameter():判断是否支持参数解析方法;resolveArgument():具体的参数解析方法。

 1 // 参数处理器接口
 2 public interface HandlerMethodArgumentResolver {
 3 
 4    // 当前参数处理器是否支持MethodParameter参数的解析
 5    boolean supportsParameter(MethodParameter parameter);
 6 
 7    // 从request请求中解析MethodParameter变成参数值并返回
 8    Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
 9          NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
10 
11 }

  MVC容器中默认提供26种参数解析器:

 

 

 

1.2、返回值处理器

  初始化返回值处理器,并将获取到的返回值处理器设置进HandlerMethodReturnValueHandlerComposite的returnValueHandlers属性中,MVC容器中实现的默认返回值处理器如下:

获取默认返回值处理器器 RequestMappingHandlerAdapter#getDefaultReturnValueHandlers() 核心伪代码

 1 // 获取默认的返回值处理器
 2 private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
 3    // 保存返回值处理器集合
 4    List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(20);
 5 
 6    // 单一返回值处理器
 7    handlers.add(new ModelAndViewMethodReturnValueHandler());
 8    handlers.add(new ModelMethodProcessor());
 9    handlers.add(new ViewMethodReturnValueHandler());
10    handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),
11          this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));
12    handlers.add(new StreamingResponseBodyReturnValueHandler());
13    handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
14          this.contentNegotiationManager, this.requestResponseBodyAdvice));
15    handlers.add(new HttpHeadersReturnValueHandler());
16    handlers.add(new CallableMethodReturnValueHandler());
17    handlers.add(new DeferredResultMethodReturnValueHandler());
18    handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
19 
20    // 基于注解的返回值类型处理器
21    handlers.add(new ModelAttributeMethodProcessor(false));
22    handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),
23          this.contentNegotiationManager, this.requestResponseBodyAdvice));
24 
25    // 多返回值处理器
26    handlers.add(new ViewNameMethodReturnValueHandler());
27    handlers.add(new MapMethodProcessor());
28 
29    // 自定义返回值处理器
30    if (getCustomReturnValueHandlers() != null) {
31       handlers.addAll(getCustomReturnValueHandlers());
32    }
33 
34    // Catch-all
35    if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
36       handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
37    }
38    else {
39       handlers.add(new ModelAttributeMethodProcessor(true));
40    }
41 
42    return handlers;
43 }

  返回值处理器的顶级接口HandlerMethodReturnValueHandler包含两个核心方法:supportsReturnType()、handleReturnValue()

  supportsReturnType():判断是否支持参数解析方法;handleReturnValue():具体的参数解析方法。
 1 // 返回值处理器接口
 2 public interface HandlerMethodReturnValueHandler {
 3 
 4    // 是否支持当前返回值类型的处理
 5    boolean supportsReturnType(MethodParameter returnType);
 6     
 7    // 返回值参数解析
 8    void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
 9          ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
10  
11 }

  MVC容器中默认提供15种参数解析器

 

2、设置参数处理器

  将RequestMappingHandlerAdapter中的参数处理器属性argumentResolvers设置到ServletInvocableHandlerMethod父类InvocableHandlerMethod中的resolvers属性中。
InvocableHandlerMethod#setHandlerMethodArgumentResolvers() 核心代码:
1 // 设置参数处理器到ServletInvocableHandlerMethod的父类InvocableHandlerMethod中的resolvers属性
2 public void setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverComposite argumentResolvers) {
3    this.resolvers = argumentResolvers;
4 }

3、设置返回值处理器

  将RequestMappingHandlerAdapter中的返回值处理器器属性returnValueHandlers设置到ServletInvocableHandlerMethod类型的对象中。

  ServletInvocableHandlerMethod#returnValueHandlers() 核心代码:

1 // 设置返回值处理器到returnValueHandlers属性
2 public void setHandlerMethodReturnValueHandlers(HandlerMethodReturnValueHandlerComposite returnValueHandlers) {
3    this.returnValueHandlers = returnValueHandlers;
4 }

4、设置@InitBinder处理工厂

  将获取到的WebDataBinderFactory设置到ServletInvocableHandlerMethod父类InvocableHandlerMethod中的dataBinderFactory属性中。

  InvocableHandlerMethod#setDataBinderFactory() 核心代码:

1 // 设置@InitBinder处理工厂到ServletInvocableHandlerMethod的父类InvocableHandlerMethod中的dataBinderFactory属性
2 public void setDataBinderFactory(WebDataBinderFactory dataBinderFactory) {
3    this.dataBinderFactory = dataBinderFactory;
4 }

5、设置名称发现器

  参数名称发现器parameterNameDiscoverer是RequestMappingHandlerAdapter中的属性,属性详情如下:

// 创建参数名称发现器
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

  在DefaultParameterNameDiscoverer构造函数中添加了名称发现器:KotlinReflectionParameterNameDiscoverer、StandardReflectionParameterNameDiscoverer、LocalVariableTableParameterNameDiscoverer

1 public DefaultParameterNameDiscoverer() {
2    if (KotlinDetector.isKotlinReflectPresent() && !GraalDetector.inImageCode()) {
3       addDiscoverer(new KotlinReflectionParameterNameDiscoverer());
4    }
5    addDiscoverer(new StandardReflectionParameterNameDiscoverer());
6    addDiscoverer(new LocalVariableTableParameterNameDiscoverer());
7 }

5、创建ModelAndViewContainer对象并完成属性设置

  ModelAndViewContainer对象的view和model属性:

 1 public class ModelAndViewContainer {
 2     
 3     // 是否不使用defaultModel属性标识
 4     private boolean ignoreDefaultModelOnRedirect = false;
 5     
 6     // ModelAndViewContainer的view属性
 7     private Object view;
 8     
 9     // ModelAndViewContainer的默认Model属性
10     private final ModelMap defaultModel = new BindingAwareModelMap();
11     
12     // ModelAndViewContainer的Model属性
13     private ModelMap redirectModel;
14 }

  初始创建mavContainer对象,view属性和model属性为空,在执行完成handler处理器后,对view和model属性进行填充。

  ModelAndViewContainer的model属性,BindingAwareModelMap类图如下,在实际填充ModelAndViewContainer的model属性,主要调用父类ExtendedModelMap、ModeMap中的方法,详细填充过程后续会进行分析。

  

6、调用handler执行器

  调用handler执行器主要有三个步骤:请求参数解析、返回值结果解析、ModelAndViewContainer的Model属性、View属性填充。

  ServletInvocableHandlerMethod #invokeAndHandle() 核心伪代码

 1 // 调用处理Handler处理器
 2 public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
 3       Object... providedArgs) throws Exception {
 4 
 5    // 调用父类的invokeForRequest执行请求
 6    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
 7    
 8    // 处理@ResponseStatus注解
 9    setResponseStatus(webRequest);
10    // ...
11    // RequestHandled为false 即请求完成
12    mavContainer.setRequestHandled(false);
13 
14    // 使用returnValueHandlers处理返回值
15    this.returnValueHandlers.handleReturnValue(
16             returnValue, getReturnValueType(returnValue), mavContainer, webRequest);  
17 }

1、调用父类执行请求并获取返回结果

  InvocableHandlerMethod#invokeForRequest 核心伪代码
1 public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
2       Object... providedArgs) throws Exception {
3 
4    // 准备方法所需要的参数
5    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
6 
7    // 真正调用的method
8    return doInvoke(args);
9 }

1.1、获取方法参数getMethodArgumentValues

  InvocableHandlerMethod#getMethodArgumentValues() 核心伪代码

 1 protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
 2       Object... providedArgs) throws Exception {
 3 
 4    // 获取方法的参数,HandlerMethod中的parameters属性
 5    MethodParameter[] parameters = getMethodParameters();
 6    // 参数若为空,返回空参数数组
 7    if (ObjectUtils.isEmpty(parameters)) {
 8       return EMPTY_ARGS;
 9    }
10 
11    // 用于保存解析出参数的值
12    Object[] args = new Object[parameters.length];
13    for (int i = 0; i < parameters.length; i++) {
14       MethodParameter parameter = parameters[i];
15       // 给parameter设置参数名解析器
16       parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
17       // 如果相应类型的参数已经在providedArgs中提供了,则直接设置到parameter
18       args[i] = findProvidedArgument(parameter, providedArgs);
19       if (args[i] != null) {
20          continue;
21       }
22       // 若参数解析器无法解析参数,抛出异常
23       if (!this.resolvers.supportsParameter(parameter)) {
24          throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
25       }
26       
27       // 使用argumentResolvers参数解析器解析参数
28       args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
29      
30    }
31    return args;
32 }
1、方法为无参数方法,返回空参数数组

  获取HandlerMethod中的parameters属性,在源码(六):Handler处理器获取中,有具体的HandlerMethod的获取过程,此处不再赘述。

2、方法为有参方法,解析参数

  遍历方法参数,判断参数解析器集合中是否支持参数解析,若解析器集合不支持当前参数的解析,抛出异常,流程结束;若解析器集合支持当前参数的解析,调用参数解析器的resolveArgument()方法实现方法参数的解析,并将解析的结果放入args集合返回。

1.2、doInvoke -> 调用Controller控制器的指定方法

  

 在执行完Controller控制器的处理逻辑后,已经填充了ModelAndViewContainer的defaultModel属性。

  

1、ModelAndViewContainer的model属性填充
  下面我们来看看ModelAndViewContainer的defaultModel的Model属性是如何被填充的,分析hello()方法,唯一可添加model属性的步骤在model.addAttribute()方法。
ExtendedModelMap#addAttribute() 核心伪代码:
1 // 设置ModleAndViewContainer的model属性
2 public ExtendedModelMap addAttribute(String attributeName, @Nullable Object attributeValue) {
3    // 添加属性
4    super.addAttribute(attributeName, attributeValue);
5    return this;
6 }

  传入参数如下:

  

  ModelMap#addAttribute() 核心伪代码

1 public ModelMap addAttribute(String attributeName, @Nullable Object attributeValue) {
2    // 设置属性名称、属性值
3    put(attributeName, attributeValue);
4    return this;
5 }

  BindingAwareModelMap#put()

1 // 填充ModelAndViewContainer的Model属性
2 public Object put(String key, @Nullable Object value) {
3    // 清空重复的属性值、属性名称
4    removeBindingResultIfNecessary(key, value);、
5    // 填充属性
6    return super.put(key, value);
7 }
2、Controller控制器返回结果
  回到Controller控制器执行流程,获取返回结果userlist字符串。

  

 

 

2、返回结果的处理

  处理Controller控制器返回结果,HandlerMethodReturnValueHandlerComposite#handleReturnValue 核心伪代码

 1 // 处理Controller控制器返回结果
 2 public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
 3       ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
 4    // 获取返回值处理器
 5    HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
 6    // 未匹配到返回值处理器,抛出异常
 7    if (handler == null) {
 8       throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
 9    }
10    // 调用处理器处理返回值
11    handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
12 }

1、匹配返回值处理器

  匹配返回值处理器,HandlerMethodReturnValueHandlerComposite#selectHandler() 核心伪代码
 1 // 获取返回值处理器
 2 private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
 3    // 异步处理返回值标识
 4    boolean isAsyncValue = isAsyncReturnValue(value, returnType);
 5    // 遍历返回值处理器
 6    for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
 7       // 若异步处理返回值标识为true并且当前返回值处理器不为AsyncHandlerMethodReturnValueHandler异步返回值处理器,跳过
 8       if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
 9          continue;
10       }
11       // 当前返回值处理器是否能处理Controller控制器返回结果
12       if (handler.supportsReturnType(returnType)) {
13          // 返回目标返回值处理器
14          return handler;
15       }
16    }
17    // 无匹配的返回值处理器,返回null
18    return null;
19 }
1、遍历MVC默认实现的返回值处理器

  debug调试,获取返回值处理器ViewNameMethodReturnValueHandler,ViewNameMethodReturnValueHandler实现了返回值处理器的顶级接口HandlerMethodReturnValueHandler。

  

下面来看看ViewNameMethodReturnValueHandler对核心方法supportsReturnType()的实现, ViewNameMethodReturnValueHandler#supportsReturnType() 核心代码:

1 // 是否能处理返回值
2 public boolean supportsReturnType(MethodParameter returnType) {
3    // 获取返回值的类型  Class对象
4    Class<?> paramType = returnType.getParameterType();、
5    // ViewNameMethodReturnValueHandler可处理的返回值类型为void、CharSequence
6    return (void.class == paramType || CharSequence.class.isAssignableFrom(paramType));
7 }

  本次演示案例Contoller返回值为"userlist"为String类型,String实现了CharSequence接口,因此返回值处理器ViewNameMethodReturnValueHandler可处理String类型的返回结果。

 

2、调用处理器处理返回值

  ViewNameMethodReturnValueHandler对核心方法supportsReturnType()的实现已经分析,下面来看看ViewNameMethodReturnValueHandler对返回值处理的核心方法handleReturnValue()的实现。

  ViewNameMethodReturnValueHandler#handleReturnValue() 核心代码

 1 // 处理器处理返回值结果
 2 public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
 3       ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
 4    // 返回值类型为CharSequence类型
 5    if (returnValue instanceof CharSequence) {
 6       // 获取视图名称
 7       String viewName = returnValue.toString();
 8       // 将视图名称设置进mavContainer对象的view属性
 9       mavContainer.setViewName(viewName);
10       // 若为重定向视图,是指重定向标识为true
11       if (isRedirectViewName(viewName)) {
12          mavContainer.setRedirectModelScenario(true);
13       }
14    }
15    // 若返回值不为null。抛出异常
16    else if (returnValue != null) {
17       throw new UnsupportedOperationException("Unexpected return type: " +
18             returnType.getParameterType().getName() + " in method: " + returnType.getMethod());
19    }
20 }

  1、返回值类型为CharSequence,即字符串类型,获取返回视图名称,并将视图设置进ModelAndViewContainer中的view属性;

  2、若重定向视图,则将重定向表示设置为true。

3、总结

  调用Controller控制的目标方法,将返回数据设置在ModelAndViewContainer的model属性中,将返回视图设置在在ModelAndViewContainer的view属性中。

7、获取ModelAndView对象

  获取ModelAndView对象,RequestMappingHandlerAdapter#getModelAndView() 核心伪代码
 1 // 获取ModelAndView对象
 2 private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
 3       ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
 4 
 5    // 更新model(设置sessionAttributes和给model设置BindingResult)
 6    modelFactory.updateModel(webRequest, mavContainer);
 7    // 若 mavContainer 已处理,则返回 null
 8    if (mavContainer.isRequestHandled()) {
 9       return null;
10    }
11    // 若 mavContainer未处理,基于mavContainer生成ModelAndView对象
12    ModelMap model = mavContainer.getModel();
13    // 创建 ModelAndView 对象,并设置相关属性
14    ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
15    
16    // 如果mavContainer里的view不是string类型,强转为View类型,则设置到mv中
17    if (!mavContainer.isViewReference()) {
18       mav.setView((View) mavContainer.getView());
19    }
20    // 重定向的处理
21    if (model instanceof RedirectAttributes) {
22       Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
23       HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
24       if (request != null) {
25          RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
26       }
27    }
28    // 返回ModelAndView对象
29    return mav;
30 }

1、更新Model属性处理

  ModelFactory#updateModel() 核心代码:

 1 // Session属性处理器
 2 private final SessionAttributesHandler sessionAttributesHandler;
 3 
 4 // 更新Model属性
 5 public void updateModel(NativeWebRequest request, ModelAndViewContainer container) throws Exception {
 6    // 获取ModelAndViewContainer的Model属性
 7    ModelMap defaultModel = container.getDefaultModel();
 8    // 判断ModelAndViewContainer中的SessionStatus是否为已完成
 9    if (container.getSessionStatus().isComplete()){
10       // 清理WebRequest请求中的attribute属性
11       this.sessionAttributesHandler.cleanupAttributes(request);
12    }
13    else {
14       // 将model属性设置到WebRequest请求
15       this.sessionAttributesHandler.storeAttributes(request, defaultModel);
16    }
17    // 请求是否未处理完成,ModelAndViewContainer中的model为默认的Model类型
18    if (!container.isRequestHandled() && container.getModel() == defaultModel) {
19       // 将数据绑定结果设置到Model属性中
20       updateBindingResult(request, defaultModel);
21    }
22 }

  1.1、判断ModelAndViewContainer中的Session属性处理标识是否为已完成,若为已完成,则清除WebReqquest中的Session属性;若未完成,则将ModelAndViewContainer中的mode属性设置到WebRequest请求中。

  1.2、Request请求未处理器完成,ModelAndViewContainer中的model为默认的Model类型,将数据绑定的结果设置到Model属性中。

2、ModelAndViewContainer请求处理判断

2.1、ModelAndViewContainer已处理,返回null

2.2、ModelAndViewContainer未处理

  创建ModelAndView对象,并用ModelAndViewContainer对象中的Model属性、View属性初始化创建的ModelAndView对象。

 1 // ModelAndView构造器
 2 public ModelAndView(@Nullable String viewName, @Nullable Map<String, ?> model, @Nullable HttpStatus status) {
 3    // 设置view视图
 4    this.view = viewName;
 5    // 设置model属性
 6    if (model != null) {
 7       getModelMap().addAllAttributes(model);
 8    }
 9    // 设置status状态
10    this.status = status;
11 }

  如果mavContainer里的view不是string类型,强转为View类型,则设置到mv中;若mavContainer里的view是RedirectAttributes类型,获取重定向的属性值flashAttributes设置到WebRequest对象的attributes中,填充WebRequest对象。

3、Controller执行完成,返回ModelAndView对象

 

posted @ 2023-02-16 20:32  无虑的小猪  阅读(454)  评论(0编辑  收藏  举报