上一级页面:ssm-spring-boot速成学习索引
前言
本节描述,一个请求发送到DispatcherServlet后的具体处理流程,也就是SpringMVC的主要原理。
本节内容较多且硬核,对日后编程很有帮助,需耐心对待。
本节第一遍有一个耳熟,有大致印象即可,不明白就再听一遍本节,循环往复,直到听明白。
听明白后,一定要课后复盘一次,自己用IDE调试走完一遍流程。
名词解释
debug工具中有许多专有名词,它们需要记忆,以方便理解其他程序员调试的时候到底在说什么。
图中红框按钮,从左到右依次是
step-over 步过:即在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数整个执行完再停止,也就是把子函数整个作为一步。
step-into 步入:单步执行,遇到子函数就进入并且继续单步执行。
step-out 步出:当单步执行到子函数内时,在子函数内,使用step out就可以执行完子函数余下部分,并返回到返回到上一层函数(即调用此子函数的函数)。
run-to-cursor 程序运行,并跳转到鼠标指针处在JB系中,还有这个按钮
recover-run,恢复程序运行:在当前位置顺序执行程序,执行过程中遇到断点则停留在断点。未遇到断点则恢复程序正常运行
32、请求处理-【源码分析】-各种类型参数解析原理
这要从DispatcherServlet
类的doDispatch
方法开始:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class DispatcherServlet extends FrameworkServlet { 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); mappedHandler = getHandler(processedRequest); if (mappedHandler == null ) { noHandlerFound(processedRequest, response); return ; } HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); ...
先看这句:
1 mappedHandler = getHandler(processedRequest);
步入进去
1 2 3 4 5 6 7 8 9 10 11 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 ; }
HandlerMapping
中找到能处理请求的Handler
(即XXXController.XXXmethod()
)。
步过,跳回到DispatcherServlet
类的doDispatch
方法,
注意这句:
1 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
步入getHandlerAdapter
方法,发现
1 2 3 4 5 6 7 8 9 10 11 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" ); }
为当前Handler 找一个适配器 HandlerAdapter
,
步过,跳回到DispatcherServlet
类的doDispatch
方法,
注意到这句
1 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
这个方法的详细解析在下一节。
小结:
HandlerMapping
中找到能处理请求的Handler
(即XXXController.XXXmethod()
)。
为当前Handler 找一个适配器 HandlerAdapter
(实际上用的最多的是RequestMappingHandlerAdapter 。)
适配器执行目标方法并确定方法参数的每一个值。
HandlerAdapter和RequestMappingHandlerAdapter
Spring的设计思想之一:适配器模式(Adapter mode)
上一小节说到,
1 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
步入getHandlerAdapter
方法,发现
1 2 3 4 5 6 7 8 9 10 11 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" ); }
注意到this.handlerAdapters
,在DispatcherServlet
类中搜索handlerAdapters
,发现SpringBoot默认会加载所有HandlerAdapter
,大致流程如下:
找到handlerAdapters
的初始化方法
1 2 3 4 5 protected void initStrategies (ApplicationContext context) { initHandlerAdapters(context); }
Ctrl+左键,点击进入initHandlerAdapters(context);
来到DispatcherServlet
类的initHandlerAdapters
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class DispatcherServlet extends FrameworkServlet { private boolean detectAllHandlerAdapters = true ; private void initHandlerAdapters (ApplicationContext context) { this .handlerAdapters = null ; if (this .detectAllHandlerAdapters) { Map<String, HandlerAdapter> matchingBeans =BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true , false ); if (!matchingBeans.isEmpty()) { this .handlerAdapters = new ArrayList <>(matchingBeans.values()); AnnotationAwareOrderComparator.sort(this .handlerAdapters); } } ...
在这个方法中打断点调试一下,
方法执行后,查看this.handlerAdapters
发现有这些HandlerAdapter
:
0
:支持方法上标注@RequestMapping
1
:支持函数式编程的
2
:….
3
:….
其中最常用的是0
:RequestMappingHandlerAdapter
执行目标方法 ha.handle(processedRequest, response, mappedHandler.getHandler())
回到DispatcherServlet
类的doDispatch
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class DispatcherServlet extends FrameworkServlet { protected void doDispatch (HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mv = null ; ... mappedHandler = getHandler(processedRequest); if (mappedHandler == null ) { noHandlerFound(processedRequest, response); return ; } HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); ... mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
注意到关键语句,来到本篇文章的解析重点:
1 2 3 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
步入进去,来到:
1 2 3 4 5 6 7 @Override @Nullable public final ModelAndView handle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); }
继续步入,来到RequestMappingHandlerAdapter
类的handleInternal
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware , InitializingBean { protected ModelAndView handleInternal (HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; checkRequest(request); if (this .synchronizeOnSession) { } else { mav = invokeHandlerMethod(request, response, handlerMethod); } } }
关键在这一行
1 2 mav = invokeHandlerMethod(request, response, handlerMethod);
步入进去,来到核心内容:invokeHandlerMethod
方法
参数解析器 argumentResolvers
核心方法supportsParameter
和resolveArgument
RequestMappingHandlerAdapter
类的invokeHandlerMethod
方法,里面有一个参数解析器 argumentResolvers
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Nullable protected ModelAndView invokeHandlerMethod (HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest (request, response); try { WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); if (this .argumentResolvers != null ) { invocableMethod.setHandlerMethodArgumentResolvers(this .argumentResolvers); } ...
注意图中红框标记位置
前面都是一些初始化相关的语句,来到关键语句:
1 2 3 if (this .argumentResolvers != null ) { invocableMethod.setHandlerMethodArgumentResolvers(this .argumentResolvers); }
参数解析器确定将要执行的目标方法的每一个参数的值是什么;
评估表达式,得到结果:
发现Spring MVC加载了大量的参数解析器argumentResolvers
SpringMVC目标方法能写多少种参数类型。取决于参数解析器argumentResolvers 。
按住Ctrl,点击this.argumentResolvers
,发现它是HandlerMethodArgumentResolverComposite
类型的
查看这个类HandlerMethodArgumentResolverComposite
,发现它实现接口HandlerMethodArgumentResolver
查看接口HandlerMethodArgumentResolver
,在接口中,按Ctrl+F12:
这里是Spring的参数解析器核心设计,是本篇内容的核心点,后面的解析都紧扣这两个方法:
boolean supportsParameter(MethodParameter parameter);
当前解析器是否支持解析传进来的这种参数
Object resolveArgument();
支持就调用这个方法进行解析,不支持就返回false
argumentResolvers
的初始化过程
通过双击调试栈的栈顶元素,回到RequestMappingHandlerAdapter
类,
在RequestMappingHandlerAdapter
类中搜索argumentResolvers
,
查找argumentResolvers
的初始化过程,发现this.argumentResolvers
在afterPropertiesSet()
方法内初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware , InitializingBean { @Nullable private HandlerMethodArgumentResolverComposite argumentResolvers; @Override public void afterPropertiesSet () { ... if (this .argumentResolvers == null ) { List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers(); this .argumentResolvers = new HandlerMethodArgumentResolverComposite ().addResolvers(resolvers); } ... }
getDefaultArgumentResolvers
方法
通过Ctrl+点击,查看getDefaultArgumentResolvers
方法。
发现这个方法初始化了一堆的实现HandlerMethodArgumentResolver
接口的参数解析器ArgumentResolver
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers () { List<HandlerMethodArgumentResolver> resolvers = new ArrayList <>(30 ); resolvers.add(new RequestParamMethodArgumentResolver (getBeanFactory(), false )); resolvers.add(new RequestParamMapMethodArgumentResolver ()); resolvers.add(new PathVariableMethodArgumentResolver ()); resolvers.add(new PathVariableMapMethodArgumentResolver ()); resolvers.add(new MatrixVariableMethodArgumentResolver ()); resolvers.add(new MatrixVariableMapMethodArgumentResolver ()); resolvers.add(new ServletModelAttributeMethodProcessor (false )); resolvers.add(new RequestResponseBodyMethodProcessor (getMessageConverters(), this .requestResponseBodyAdvice)); resolvers.add(new RequestPartMethodArgumentResolver (getMessageConverters(), this .requestResponseBodyAdvice)); resolvers.add(new RequestHeaderMethodArgumentResolver (getBeanFactory())); resolvers.add(new RequestHeaderMapMethodArgumentResolver ()); resolvers.add(new ServletCookieValueMethodArgumentResolver (getBeanFactory())); resolvers.add(new ExpressionValueMethodArgumentResolver (getBeanFactory())); resolvers.add(new SessionAttributeMethodArgumentResolver ()); resolvers.add(new RequestAttributeMethodArgumentResolver ()); resolvers.add(new ServletRequestMethodArgumentResolver ()); resolvers.add(new ServletResponseMethodArgumentResolver ()); resolvers.add(new HttpEntityMethodProcessor (getMessageConverters(), this .requestResponseBodyAdvice)); resolvers.add(new RedirectAttributesMethodArgumentResolver ()); resolvers.add(new ModelMethodProcessor ()); resolvers.add(new MapMethodProcessor ()); resolvers.add(new ErrorsMethodArgumentResolver ()); resolvers.add(new SessionStatusMethodArgumentResolver ()); resolvers.add(new UriComponentsBuilderMethodArgumentResolver ()); if (KotlinDetector.isKotlinPresent()) { resolvers.add(new ContinuationHandlerMethodArgumentResolver ()); } if (getCustomArgumentResolvers() != null ) { resolvers.addAll(getCustomArgumentResolvers()); } resolvers.add(new PrincipalMethodArgumentResolver ()); resolvers.add(new RequestParamMethodArgumentResolver (getBeanFactory(), true )); resolvers.add(new ServletModelAttributeMethodProcessor (true )); return resolvers; } }
HandlerMethodArgumentResolverComposite
回到afterPropertiesSet()
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public void afterPropertiesSet () { initControllerAdviceCache(); initMessageConverters(); 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); } }
注意到HandlerMethodArgumentResolverComposite
类
这个类是众多参数解析器argumentResolvers的包装类
,
对于包装类,一般包装单个的命名为warpper。包装多个的命名为Composite
内容大致如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver { private final List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList <>(); ... public HandlerMethodArgumentResolverComposite addResolvers ( @Nullable HandlerMethodArgumentResolver... resolvers) { if (resolvers != null ) { Collections.addAll(this .argumentResolvers, resolvers); } return this ; } ... }
类HandlerMethodArgumentResolverComposite
实现了接口HandlerMethodArgumentResolver
接口HandlerMethodArgumentResolver
源码大致如下:
1 2 3 4 5 6 7 8 9 10 11 public interface HandlerMethodArgumentResolver { boolean supportsParameter (MethodParameter parameter) ; @Nullable Object resolveArgument (MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;}
返回值处理器 ReturnValueHandler
类似于上一节对参数解析器的调试分析过程,对返回值处理器ReturnValueHandler做解析:
点击栈顶元素,回到RequestMappingHandlerAdapter
类的invokeHandlerMethod
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Nullable protected ModelAndView invokeHandlerMethod (HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest (request, response); try { WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); 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); } ...
注意到
1 2 3 if (this .returnValueHandlers != null ) { invocableMethod.setHandlerMethodReturnValueHandlers(this .returnValueHandlers); }
通过类似的搜索方法,发现this.returnValueHandlers
在afterPropertiesSet()
方法内初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware , InitializingBean { @Nullable private HandlerMethodReturnValueHandlerComposite returnValueHandlers; @Override public void afterPropertiesSet () { ... if (this .returnValueHandlers == null ) { List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers(); this .returnValueHandlers = new HandlerMethodReturnValueHandlerComposite ().addHandlers(handlers); } }
查看getDefaultReturnValueHandlers
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers () { List<HandlerMethodReturnValueHandler> handlers = new ArrayList <>(20 ); handlers.add(new ModelAndViewMethodReturnValueHandler ()); handlers.add(new ModelMethodProcessor ()); handlers.add(new ViewMethodReturnValueHandler ()); handlers.add(new ResponseBodyEmitterReturnValueHandler (getMessageConverters(), this .reactiveAdapterRegistry, this .taskExecutor, this .contentNegotiationManager)); handlers.add(new StreamingResponseBodyReturnValueHandler ()); handlers.add(new HttpEntityMethodProcessor (getMessageConverters(), this .contentNegotiationManager, this .requestResponseBodyAdvice)); handlers.add(new HttpHeadersReturnValueHandler ()); handlers.add(new CallableMethodReturnValueHandler ()); handlers.add(new DeferredResultMethodReturnValueHandler ()); handlers.add(new AsyncTaskMethodReturnValueHandler (this .beanFactory)); handlers.add(new ServletModelAttributeMethodProcessor (false )); handlers.add(new RequestResponseBodyMethodProcessor (getMessageConverters(), this .contentNegotiationManager, this .requestResponseBodyAdvice)); handlers.add(new ViewNameMethodReturnValueHandler ()); handlers.add(new MapMethodProcessor ()); if (getCustomReturnValueHandlers() != null ) { handlers.addAll(getCustomReturnValueHandlers()); } if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) { handlers.add(new ModelAndViewResolverMethodReturnValueHandler (getModelAndViewResolvers())); } else { handlers.add(new ServletModelAttributeMethodProcessor (true )); } return handlers; } }
查看HandlerMethodReturnValueHandlerComposite
类,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodReturnValueHandler { private final List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList <>(); ... public HandlerMethodReturnValueHandlerComposite addHandlers ( @Nullable List<? extends HandlerMethodReturnValueHandler> handlers) { if (handlers != null ) { this .returnValueHandlers.addAll(handlers); } return this ; } }
注意到实现了HandlerMethodReturnValueHandler
接口:
1 2 3 4 5 6 7 8 public interface HandlerMethodReturnValueHandler { boolean supportsReturnType (MethodParameter returnType) ; void handleReturnValue (@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;}
定位到真正执行目标方法 doInvoke(args)
结束之前的调试,
重新开始调试,从DispatcherServlet
类的doDispatch
方法开始,在这打个断点
1 2 3 4 5 6 public class DispatcherServlet extends FrameworkServlet { ... protected void doDispatch (HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mv = null ; ... mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
发现关键的执行目标方法语句:
1 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
步入ha.handle()
,来到RequestMappingHandlerAdapter
的handle()
方法:
1 2 3 4 5 public final ModelAndView handle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); }
继续步入,来到类RequestMappingHandlerAdapter
的handleInternal
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware , InitializingBean { @Override protected ModelAndView handleInternal (HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; mav = invokeHandlerMethod(request, response, handlerMethod); return mav; } }
发现核心的执行方法
1 2 mav = invokeHandlerMethod(request, response, handlerMethod);
继续步入invokeHandlerMethod()
进去,
RequestMappingHandlerAdapter
的invokeHandlerMethod()
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware , InitializingBean { protected ModelAndView invokeHandlerMethod (HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest (request, response); try { ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); if (this .argumentResolvers != null ) { invocableMethod.setHandlerMethodArgumentResolvers(this .argumentResolvers); } if (this .returnValueHandlers != null ) { invocableMethod.setHandlerMethodReturnValueHandlers(this .returnValueHandlers); } invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null ; } return getModelAndView(mavContainer, modelFactory, webRequest); } finally { webRequest.requestCompleted(); } }
注意到执行目标方法的语句:
1 2 3 invocableMethod.invokeAndHandle(webRequest, mavContainer);
步入进去invocableMethod.invokeAndHandle()
方法,
invokeAndHandle()
方法如下:
1 2 3 4 5 6 7 public class ServletInvocableHandlerMethod extends InvocableHandlerMethod { public void invokeAndHandle (ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); setResponseStatus(webRequest);
给这个方法内打上两个断点,
并且给最终要执行的XXXController.XXXmethod
方法中打上一个断点,例如我自己编写的RequestController
中的bossAge
方法
在Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
处
按恢复程序执行
按钮,它会从当前位置开始,顺序执行程序,知道遇到下一个断点。
结果发现跳转到最终要执行的XXXController.XXXmethod
方法。
说明这里的invokeForRequest
方法就是我们要找的真正执行目标方法。关键语句如下:
1 2 Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
步入invokeForRequest
方法,
发现两个关键语句
1 2 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
步入doInvoke
,来到doInvoke
方法
已经开始调用反射工具类了,说明这里已经到达业务逻辑的最底层了
总结:通过本小节的内容,一步一步使用IDE的断点调试工具,找到了框架最底层调用反射工具类的方法。找到了真正的执行方法doInvoke
方法
定位到ServletInvocableHandlerMethod
类的getMethodArgumentValues
方法
先结束上面的调试。
重新开始调试,遵循上一小节的步骤,来到invokeForRequest()
方法
1 2 3 4 5 6 7 8 9 public Object invokeForRequest (NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); if (logger.isTraceEnabled()) { logger.trace("Arguments: " + Arrays.toString(args)); } return doInvoke(args); }
注意到这里的getMethodArgumentValues
1 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
步入getMethodArgumentValues
方法,来到关键方法getMethodArgumentValues()
1 2 3 4 5 6 7 protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; }
定位到ServletInvocableHandlerMethod
类,getMethodArgumentValues
方法
获取当前请求(request)的方法参数值(Method Argument Values)getMethodArgumentValues()
分析ServletInvocableHandlerMethod
类的的getMethodArgumentValues
方法
Get the method argument values for the current request, checking the provided argument values and falling back to the configured argument resolvers.
The resulting array will be passed into doInvoke.
例如对于url
1 http://localhost:8080/api/boss/001;age=34;jobs=开发,研发
通过这个方法 getMethodArgumentValues()
能够解析出来,结果args如下:
大致源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class ServletInvocableHandlerMethod extends InvocableHandlerMethod { ... @Nullable public Object invokeForRequest (NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; } Object[] args = new Object [parameters.length]; for (int i = 0 ; i < parameters.length; i++) { MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this .parameterNameDiscoverer); args[i] = findProvidedArgument(parameter, providedArgs); if (args[i] != null ) { continue ; } if (!this .resolvers.supportsParameter(parameter)) { throw new IllegalStateException (formatArgumentError(parameter, "No suitable resolver" )); } try { args[i] = this .resolvers.resolveArgument(parameter, mavContainer, request, this .dataBinderFactory); } catch (Exception ex) { .... } } return args; } }
其中重点语句有2个
1 2 3 if (!this .resolvers.supportsParameter(parameter)) {}
1 args[i] = this .resolvers.resolveArgument(parameter, mavContainer, request, this .dataBinderFactory);
会在接下来的小节中继续分析
遍历查找参数解析器(Argument resolver)
注意到这句:
1 2 3 4 if (!this .resolvers.supportsParameter(parameter)) { throw new IllegalStateException (formatArgumentError(parameter, "No suitable resolver" )); }
其中this.resolvers.supportsParameter(parameter)
是本小节的重点。
这个函数的目标是找到,支持解析对应参数的参数值解析器(Argument Values resolver)
首先评估表达式this.resolvers
,发现this.resolvers
的类型为HandlerMethodArgumentResolverComposite
(在参数解析器 argumentResolvers 章节提及)
现在,步入this.resolvers.supportsParameter
,来到HandlerMethodArgumentResolverComposite
类的supportsParameter
方法。
1 2 3 4 @Override public boolean supportsParameter (MethodParameter parameter) { return getArgumentResolver(parameter) != null ; }
继续步入,来到方法getArgumentResolver
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Nullable private HandlerMethodArgumentResolver getArgumentResolver (MethodParameter parameter) { HandlerMethodArgumentResolver result = this .argumentResolverCache.get(parameter); if (result == null ) { for (HandlerMethodArgumentResolver resolver : this .argumentResolvers) { if (resolver.supportsParameter(parameter)) { result = resolver; this .argumentResolverCache.put(parameter, result); break ; } } } return result; }
注意到这个增强for循环,是关键语句
1 2 3 4 5 6 7 8 9 for (HandlerMethodArgumentResolver resolver : this .argumentResolvers) { if (resolver.supportsParameter(parameter)) { result = resolver; this .argumentResolverCache.put(parameter, result); break ; } }
遍历判断参数解析器(resolver),找到支持解析这个参数的参数解析器(resolver)
找到了先缓存起来,
返回找到的结果result
解析流程–使用参数解析器(Argument resolver)进行解析
步出,回到方法getMethodArgumentValues
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { args[i] = findProvidedArgument(parameter, providedArgs); if (args[i] != null ) { continue ; } if (!this .resolvers.supportsParameter(parameter)) { throw new IllegalStateException (formatArgumentError(parameter, "No suitable resolver" )); } try { args[i] = this .resolvers.resolveArgument(parameter, mavContainer, request, this .dataBinderFactory); }
注意到语句
1 args[i] = this .resolvers.resolveArgument(parameter, mavContainer, request, this .dataBinderFactory);
步入进去:
来到HandlerMethodArgumentResolverComposite
类的resolveArgument
方法
1 2 3 4 5 6 7 8 9 10 11 12 @Override @Nullable public Object resolveArgument (MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null ) { throw new IllegalArgumentException ("Unsupported parameter type [" + parameter.getParameterType().getName() + "]. supportsParameter should be called first." ); } return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); }
在这里
首先getArgumentResolver(parameter);
获取前文遍历得到的参数解析器argumentResolvers
然后return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
使用参数解析器执行解析操作。
最终得到参数的值,例如下图中的”34“、“开发,研发”,都是通过参数解析器获得的参数值。
debug来到return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
,就已经到达了业务逻辑的最底层。因为再往下深究,就是底层的工具类了。
小结
核心语句:
1 2 3 4 5 6 7 8 if (!this .resolvers.supportsParameter(parameter)) { throw new IllegalStateException (formatArgumentError(parameter, "No suitable resolver" )); } try { args[i] = this .resolvers.resolveArgument(parameter, mavContainer, request, this .dataBinderFactory); }
this.resolvers.supportsParameter(parameter)
遍历获得对应的参数解析器
this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory)
使用上文获得的参数解析器来解析参数,得到参数的值
本节描述,一个请求发送到DispatcherServlet后的具体处理流程,也就是SpringMVC的主要原理。
本节内容较多且硬核,对日后编程很有帮助,需耐心对待。
学习本节时,要运行一个示例,打断点,在Debug模式下,查看程序流程。
本节课的重要内容是掌握断点调试Debug。本节课演示了如果通过debug,一步一步搞清出程序的执行流程,这是本节课必须要掌握的。
本节课还在debug的过程中介绍了spring的一些设计思想,spring在代码复用等方面的写法,这些是很好的范例,要求学习和了解,在以后的工作中会有机会运用。
SpringBootWeb开发-2-3
spring-boot-web-开发-2-3-源码分析
参考、引用、致谢