springMvc - Mapping匹配过程
2019-08-22 19:52:07 32 举报
AI智能生成
SpringMVC请求过程,当一个请求传来时,Spring都做了什么
作者其他创作
大纲/内容
一个get请求,/myjava/game/games.do?gameId=1时,springMVC会做什么
1. 扫描controller注解和requstMapping注解的类
初始化成handlerMethod
初始化成handlerMethod
HttpServletBean.init
将配置参数映射到此servlet的bean属性,并调用子类初始化。
FrameworkServlet.initServletBean
FrameworkServlet.initWebApplicationContext
初始化WebApplicationContext
FrameworkServlet.createWebApplicationContext
创建WebApplicationContext
FrameworkServlet.configureAndRefreshWebApplicationContext
AbstractApplicationContext.refresh
spring上下文初始化bean的方法
AbstractApplicationContext.finishBeanFactoryInitialization
完成此上下文的全部bean工厂初始化
DefaultListbleBeanFactory.preInstantiateSingletons
批量实例化单例模式bean,获取bean
AbstractBeanFactory.getBean
AbstractBeanFactory.doGetBean
DefaultSingletonBeanRegistry.getSingleton
AbstractAutowireCapableBeanFactory.createBean
AbstractAutowireCapableBeanFactory.doCreateBean
AbstractAutowireCapableBeanFactory.initializeBean
AbstractAutowireCapableBeanFactory.invokeInitMethods
RequestMappingHandlerMapping.afterPropertiesSet
AbstractHandlerMethodMapping.afterPropertiesSet
初始化时检查方法处理器
将配置参数映射到此servlet的bean属性,并调用子类初始化。
FrameworkServlet.initServletBean
FrameworkServlet.initWebApplicationContext
初始化WebApplicationContext
FrameworkServlet.createWebApplicationContext
创建WebApplicationContext
FrameworkServlet.configureAndRefreshWebApplicationContext
AbstractApplicationContext.refresh
spring上下文初始化bean的方法
AbstractApplicationContext.finishBeanFactoryInitialization
完成此上下文的全部bean工厂初始化
DefaultListbleBeanFactory.preInstantiateSingletons
批量实例化单例模式bean,获取bean
AbstractBeanFactory.getBean
AbstractBeanFactory.doGetBean
DefaultSingletonBeanRegistry.getSingleton
AbstractAutowireCapableBeanFactory.createBean
AbstractAutowireCapableBeanFactory.doCreateBean
AbstractAutowireCapableBeanFactory.initializeBean
AbstractAutowireCapableBeanFactory.invokeInitMethods
RequestMappingHandlerMapping.afterPropertiesSet
AbstractHandlerMethodMapping.afterPropertiesSet
初始化时检查方法处理器
AbstractHandlerMethodMapping.initHandlerMethods
扫描ApplicationContext中的bean,检测和注册处理程序方法。
程序启动时执行,主要用于区分出controller和requestmapping注解的方法
扫描ApplicationContext中的bean,检测和注册处理程序方法。
程序启动时执行,主要用于区分出controller和requestmapping注解的方法
获取所有beanNames放入数组
这里获取的是springIOC中全部的Bean
包含controller,service,dao等一系列我们注册的类
这里获取的是springIOC中全部的Bean
包含controller,service,dao等一系列我们注册的类
遍历beanNames,调用RequestMappingHandlerMapping.isHandler
通过AnnotationUtils.findAnnotation(beanType, Controller.class)
处理controller注解和RequestMapping注解
通过AnnotationUtils.findAnnotation(beanType, Controller.class)
处理controller注解和RequestMapping注解
(AnnotationUtils.findAnnotation(beanType, Controller.class) != null)
(AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null)
(AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null)
从findAnnotationCacheMap中获取该bean和controller注解
findAnnotationCache 是一个线程安全的map,用于存放已经找到的AnnotationCacheKey
如果未取到值,则调用findAnnotation判断该Bean是否包含该注解
1. clazz.getDeclaredAnnotations()
常规的获取注解的方法
常规的获取注解的方法
2. 遍历注解数组,判断ann.annotationType().equals(annotationType)
此处的annotationType为controller和requestMapping,如果找到直接返回
此处的annotationType为controller和requestMapping,如果找到直接返回
3. 如果上面的遍历没有找到,则判断是否为JDK提供的注解,并且add到一个Set visited中
visited,用于保存已经访问过的annotation
4. 获取类的全部接口interface,判断接口的注解
5. 判断父类,是否包含此注解
如果找到值,则set到findAnnotationCacheMap中
detectHandlerMethods
在处理程序中寻找处理程序方法。
在处理程序中寻找处理程序方法。
1. 获取handler的Class对象
(handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass()
比如此处获取的是GameController
(handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass()
比如此处获取的是GameController
2. HandlerMethodSelectorselectMethods
选择处理器方法,其实就是获取该类GameController下的全部方法
选择处理器方法,其实就是获取该类GameController下的全部方法
3. registerHandlerMethod
遍历GameController下的全部方法来调用该方法
注册到HandlerMethodMapping中
遍历GameController下的全部方法来调用该方法
注册到HandlerMethodMapping中
根据传入的类和方法,以及方法对应的requstmapping路径创建一个HandlerMethod方法处理器类
其实是一个方法对应一个处理器,如果controller中包含多个方法,会创造多个HandlerMethod类,只不过他们的bean属性是相同的
其实是一个方法对应一个处理器,如果controller中包含多个方法,会创造多个HandlerMethod类,只不过他们的bean属性是相同的
HandlerMethod
private final Object bean;
private final BeanFactory beanFactory; 该bean的工厂
private final Class<?> beanType; controller
private final Method method; 请求路径对应的方法
this.bridgedMethod = handlerMethod.bridgedMethod;
private final MethodParameter[] parameters;
将该方法处理器类放入名为handlerMethods的Map中
key : requestMappingInfo
value : HandlerMethod类
将请求路径放入urlMap中
key : Set<String>类型的请求路径
value : requestMappingInfo
封装以下请求映射条件
匹配方式 : Patterns
请求方法 : method
请求参数 : params
url请求头 : headers
Consumes
Produces
updateNameMap
将方法处理器放入nameMap中
将方法处理器放入nameMap中
key : GC#方法名
value : HandlerMethod类
getHandlerMethods
handlerMethodsInitialized
2. 初始化handlerMapping
DispatcherServlet.initStrategies
初始化该servlet使用的策略对象
初始化该servlet使用的策略对象
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
初始化该类使用的HandlerMappings。
如果在BeanFactory中没有为这个名称空间定义HandlerMapping bean,
我们默认为BeanNameUrlHandlerMapping。
初始化该类使用的HandlerMappings。
如果在BeanFactory中没有为这个名称空间定义HandlerMapping bean,
我们默认为BeanNameUrlHandlerMapping。
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
在applicationContext中查找全部的handlerMapping,并赋值给handlerMappings集合
在applicationContext中查找全部的handlerMapping,并赋值给handlerMappings集合
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
3. 拦截分发前端请求
FrameworkServlet.service
获取请求方式 get/post/patch等
patch进入FrameworkServlet.processRequest
否则进入httpServlet.service
根据请求方式调用相应方法.如doGet
4. 根据请求查找对应的handlerMethod
并返回ModelAndView
并返回ModelAndView
例如 : 调用FrameworkServlet.doGet
FrameworkServlet.processRequest : 处理请求
FrameworkServlet重写了post,get等请求,交由processRequest方法处理
FrameworkServlet重写了post,get等请求,交由processRequest方法处理
DispatcherServlet.doService
向request中放入一些值,方便在handler中获取
DispatcherServlet.doDispatch
这步执行完之后,response中就包含了返回值
这步执行完之后,response中就包含了返回值
checkMultipart(request); 处理是否是文件上传请求
DispatcherServlet.getHandler
返回的是一个HandlerExecutionChain(执行链)
返回的是一个HandlerExecutionChain(执行链)
到这里,我们根据request的请求路径获得到了路径对应Controller和方法
1. 遍历handlerMappings
HandlerMapping接口,抽象类AbstractHandlerMapping
1. RequestMappingHandlerMapping
2. BeanNameUrlHandlerMaping
3. SimpleUrlHandlerMapping
AbstractHandlerMapping.getHandler
查询请求的处理器执行链
查询请求的处理器执行链
1. AbstractHandlerMethodMapping.getHandlerInternal
查找给定请求的处理程序方法。返回HandlerMethod类
查找给定请求的处理程序方法。返回HandlerMethod类
getUrlPathHelper
用于URL路径匹配的Helper类。提供对RequestDispatcher include中的URL路径的支持,并支持一致的URL解码。
用于URL路径匹配的Helper类。提供对RequestDispatcher include中的URL路径的支持,并支持一致的URL解码。
getLookupPathForRequest
getPathWithinServletMapping(request)
返回给定请求的servlet映射中的路径,
从request获取到/game/games.do请求路径
返回给定请求的servlet映射中的路径,
从request获取到/game/games.do请求路径
getPathWithinApplication(request)
返回给定请求的web应用程序内的路径。/game/games.do
返回给定请求的web应用程序内的路径。/game/games.do
getContextPath : 获取请求根目录/myjava
getRequestUri : 获取请求路径 (request.getRequestURI())
decodeAndCleanUriString : 解码提供的URI字符串,并去除';'后面的任何无关部分。
getRemainingPath : 去除掉请求路径中的项目名称等
getServletPath(request)
request.getServletPath()
返回servlet请求路径 /game/games.do
request.getServletPath()
返回servlet请求路径 /game/games.do
getRemainingPath
getPathWithinApplication 如果路径不为一个空字符串,则进入此方法
lookupHandlerMethod
查找当前请求的最佳匹配处理程序方法。
如果找到多个匹配项,则选择最佳匹配项。
也就是根据上一步获取的路径找到最佳匹配的包装了Controller的HandlerMethod
查找当前请求的最佳匹配处理程序方法。
如果找到多个匹配项,则选择最佳匹配项。
也就是根据上一步获取的路径找到最佳匹配的包装了Controller的HandlerMethod
根据key /game/games.do 从urlMap中获取直接匹配
urlMap中存的是全部的requestMapping地址
addMatchingMappings : 如果urlmap中获取到匹配的地址,则进入addMatchingMappings
getMatchingMapping
遍历获取urlMap的匹配结果来调用此方法
遍历获取urlMap的匹配结果来调用此方法
getMatchingCondition : 从requestMappingInfo中获取这个url的详情,包括参数,请求头,请求方法等
通过一系列参数,new一个新的requestMappingInfo并返回
new Match(match, this.handlerMethods.get(mapping))
从AbstractHandlerMethodMapping.handlerMethods的map中获取handlerMethod然后new 一个Match
从AbstractHandlerMethodMapping.handlerMethods的map中获取handlerMethod然后new 一个Match
Match是AbstractHandlerMethodMapping的一个内部类
一个用于匹配HandlerMethod及其映射的薄包装,在当前请求的上下文中与比较器比较最佳匹配。
一个用于匹配HandlerMethod及其映射的薄包装,在当前请求的上下文中与比较器比较最佳匹配。
private final T mapping;
private final HandlerMethod handlerMethod;
添加Match进集合 matches
如果集合matches有多个结果,抛出IllegalStateException异常,说明请求遇到了多个匹配项,如果不进入,则到第四步
RequestMappingInfoHandlerMapping.handleMatch
向request中set一些参数
向request中set一些参数
super.handleMatch(info, lookupPath, request)
先调用父类 AbstractHandlerMethodMapping的handlerMatch方法
先调用父类 AbstractHandlerMethodMapping的handlerMatch方法
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, lookupPath); 将路径set到request中
将一些参数set进request中,如最佳匹配模式,URI模板变量属性
return HandlerMethod.createWithResolvedBean
返回一个新的保存了controller的HandlerMethod
返回一个新的保存了controller的HandlerMethod
HandlerMethod
根据bean从Bean工厂中getBean,也就是实例化controller bean
return new HandlerMethod
2. return AbstractHandlerMapping.getHandlerExecutionChain(处理器controller,request)
构建一个新的HandlerExecutionChain(处理程序执行链,由处理程序对象和任何处理程序拦截器组成。)
构建一个新的HandlerExecutionChain(处理程序执行链,由处理程序对象和任何处理程序拦截器组成。)
如果handler是一个执行链,则直接使用此,否则根据handler创建一个执行链
HandlerExecutionChain的构造方法
HandlerExecutionChain(Object handler, HandlerInterceptor... interceptors)
在本例中执行到此步只有一个请求方法为games,ganmeController的handler
HandlerExecutionChain(Object handler, HandlerInterceptor... interceptors)
在本例中执行到此步只有一个请求方法为games,ganmeController的handler
添加拦截器.本例中未配置,为空
DispatcherServlet.getHandlerAdapter
返回适配的处理器
返回适配的处理器
遍历handlerAdapters
1. RequestMappingHandlerAdapter
2. HttpRequestHandlerAdapter
3. SimpleControllerHandlerAdapter
handlerAdapters.supports(handler)
supportsInternal(handler)
此处判断请求方式,如果是get请求...
AbstracthandlerAdaptersget.LastModified
getLastModifiedInternal : 总是返回-1
AbstractHandlerMethodAdapter.handle
使用HandlerAdapter来执行handler
到这里,我们执行完了方法,并获得了ModelAndView
此例中返回的是Null
使用HandlerAdapter来执行handler
到这里,我们执行完了方法,并获得了ModelAndView
此例中返回的是Null
RequestMappingHandlerAdapter.handleInternal
2. WebContentGenerator.checkAndPrepare (request, response, boolean lastModified)
设置缓存,默认不会执行
设置缓存,默认不会执行
checkAndPrepare
applyCacheSeconds
invokeHandleMethod
返回ModelAndView
返回ModelAndView
创建一个ServletWebRequest
getDataBinderFactory
创建 WebDataBinderFactory
创建 WebDataBinderFactory
获取handler的类型,此处为GameController
判断是否初始化过
createDataBinderFactory
getWebBindingInitializer
new ServletRequestDataBinderFactory
getModelFactory
创建ModelFactory
创建ModelFactory
与getDataBinderFactory类似
createRequestMappingMethod
创建ServletInvocableHandlerMethod
创建ServletInvocableHandlerMethod
new 一个 ServletInvocableHandlerMethod
initResponseStatus
判断是否有responseStatus注解
判断是否有responseStatus注解
setHandlerMethodArgumentResolvers 等属性
new ModelAndViewContainer
创建ModelAndView容器
创建ModelAndView容器
modelFactory.initModel
初始化model
初始化model
invokeModelAttributeMethods
调用模型属性方法来填充模型。
调用模型属性方法来填充模型。
WebAsyncUtils.createAsyncWebRequest(request, response);
异步处理相关的处理
异步处理相关的处理
ServletInvocableHandlerMethod.invokeAndHandle
这里开始绑定参数和调用我们开发的方法
这里开始绑定参数和调用我们开发的方法
InvocableHandlerMethod.invokeForRequest
截止至此,我们调用了controller方法中并获得了方法的返回值
截止至此,我们调用了controller方法中并获得了方法的返回值
在本例中就是Game类
InvocableHandlerMethod.getMethodArgumentValues
获取当前请求的方法参数值。
获取到一个Object数组,里面分别存放着方法的参数:
Game,requst,response
获取当前请求的方法参数值。
获取到一个Object数组,里面分别存放着方法的参数:
Game,requst,response
getMethodParameters
调用handlerMethod的parameters参数
调用handlerMethod的parameters参数
?????什么时候放进去的???????
是一个MethodParameter类
MethodParameter是属于哪一个HandlerMthod类
method : 参数所在的方法
parameterType : 参数类型
遍历参数用于绑定
this.argumentResolvers.supportsParameter(parameter)
判断注册的方法是否支持指定的参数
从argumentResolver中获取
判断注册的方法是否支持指定的参数
从argumentResolver中获取
HandlerMethodArgumentResolverComposite.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
参数解析,返回参数实例和值
本例中此处遍历三次,分别是Game,request,response
参数解析,返回参数实例和值
本例中此处遍历三次,分别是Game,request,response
getArgumentResolver(parameter)
从参数解析缓存中获取当前参数解析器,比如此例中的Game game
HandlerMethodArgumentResolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
从模型中解析参数,如果没有找到,则使用它的默认值实例化它。并通过数据绑定将请求
值填充进模型,并可选地验证@Valid注解是否出现在参数上。
从模型中解析参数,如果没有找到,则使用它的默认值实例化它。并通过数据绑定将请求
值填充进模型,并可选地验证@Valid注解是否出现在参数上。
截止至此,我们获得了一个绑定对象,目标类型为Game,参数名称为game,下面要为它赋值
ModelFactory.getNameForParameter(parameter);
ModelFactory.getNameForParameter(parameter);
获取参数名称game
获取参数名称game
annot = parameter.getParameterAnnotation(ModelAttribute.class);
判断字段是否被ModelAttribute注解
判断字段是否被ModelAttribute注解
String attrName = (annot != null) ? annot.value() : null;
如果被注解则取注解的值,但若注解和形参同时存在则取注解的值
如果被注解则取注解的值,但若注解和形参同时存在则取注解的值
若未被注解则使用Conventions.getVariableNameForParameter取值
判断是否是数组
判断是否是集合,若是集合,但取值为Null则报错
否则直接取参数的类型
ClassUtils.getShortNameAsProperty
去除类型的完整包名,如com.jasmine.model.Game
去除类型的完整包名,如com.jasmine.model.Game
如果从mavContainner中能根据参数名称获取到属性,则直接取,否则先创建该属性再取
此处获取的Game对象,只不过此时它的变量都为null
此处获取的Game对象,只不过此时它的变量都为null
binderFactory.createBinder
开始将参数值绑定到对象中
开始将参数值绑定到对象中
ServletRequestDataBinderFactory.createBinderInstance(target, objectName, webRequest)
参数分别为Game对象,"game"字符串,request
最终会创建一个WebDataBinder对象,target为Game,名称为game
参数分别为Game对象,"game"字符串,request
最终会创建一个WebDataBinder对象,target为Game,名称为game
ExtendedServletRequestDataBinder.ExtendedServletRequestDataBinder(Game,game)
创建实例
ServletRequestDataBinder.ServletRequestDataBinder(target, objectName);
WebDataBinder.WebDataBinder(target, objectName);
DataBinder.DataBinder
这个会判断target参数是否是class java.util.Optional,如果不是就用绑定为原来的Game
创建实例
ServletRequestDataBinder.ServletRequestDataBinder(target, objectName);
WebDataBinder.WebDataBinder(target, objectName);
DataBinder.DataBinder
这个会判断target参数是否是class java.util.Optional,如果不是就用绑定为原来的Game
initBinder
初始化绑定器
初始化绑定器
set一些值
HandlerMethod
this.bean = handler; bean = controller
this.parameters = handlerMethod.parameters;
this.parameters = handlerMethod.parameters;
this.beanFactory = handlerMethod.beanFactory; 该bean的工厂
this.beanType = handlerMethod.beanType; controller
this.method = handlerMethod.method; 请求路径对应的方法
this.bridgedMethod = handlerMethod.bridgedMethod;
ServletModelAttributeMethodProcessor.bindRequestParameters
绑定实参
到这里结束我们binder属性中
绑定实参
到这里结束我们binder属性中
的target对象的gameId的值变为了1
获取servletRequest
将绑定对象强转为ServletRequestDataBinder
ServletRequestDataBinder.bind(servletRequest)
开始绑定
开始绑定
根据request对象创建一个MutablePropertyValues
到这一步结束,我们获得一个MutablePropertyValues类
他包含我们的参数名称,参数值,用perpertyValues类的形式保存
到这一步结束,我们获得一个MutablePropertyValues类
他包含我们的参数名称,参数值,用perpertyValues类的形式保存
name = gameId , value = 1
ServletRequestParameterPropertyValues.ServletRequestParameterPropertyValues构造方法
他会先调用WebUtils.getParametersStartingWith来获取一个Map对象
获取参数对应的值
获取参数对应的值
Enumeration<String> paramNames = request.getParameterNames()
获取参数枚举
获取参数枚举
创建一个treeMap用来保存参数
paramNames.nextElement()
获取参数名gameId
获取参数名gameId
request.getParameterValues(paramName)
根据参数名获取参数值
根据参数名获取参数值
将此参数放入到map中
此时map中包含数据
此时map中包含数据
key = gameId , value = 1
如果还有其他参数继续保存,否则返回这个map
MutablePropertyValues.MutablePropertyValues(Map original)
根据返回的map调用此类的构造方法
根据返回的map调用此类的构造方法
这个类其实是propertyValue的实现类,用于保存一些容易变动的配置参数
将map放入到名为propertyValueList的集合中
addBindValues(mpvs, request)
子类可用于为请求添加额外绑定值的扩展点。在doBind(MutablePropertyValues)之前调用。默认实现为空。
子类可用于为请求添加额外绑定值的扩展点。在doBind(MutablePropertyValues)之前调用。默认实现为空。
ServletRequestDataBinder.doBind(mpvs)
在实现绑定前要执行字段默认值和标记检查
在实现绑定前要执行字段默认值和标记检查
checkFieldDefaults
检查默认值,对于以某种特殊字符开头的值,如果不存在,则使用指定值
检查默认值,对于以某种特殊字符开头的值,如果不存在,则使用指定值
checkFieldMarkers
检查以字段标记前缀开头的字段。如果字段标记存在表明字段存在于表单中。
如果属性值不包含相应的字段值,则该字段将被视为空,并将被适当重置。
检查以字段标记前缀开头的字段。如果字段标记存在表明字段存在于表单中。
如果属性值不包含相应的字段值,则该字段将被视为空,并将被适当重置。
调用DataBinder.doBind
checkAllowedFields
删除不允许的字段值
删除不允许的字段值
PropertyAccessorUtils.canonicalPropertyName
移除字段旁边的单引号或双引号
{@code map['key']} -> {@code map[key]}
{@code map["key"]} -> {@code map[key]}
移除字段旁边的单引号或双引号
{@code map['key']} -> {@code map[key]}
{@code map["key"]} -> {@code map[key]}
checkRequiredFields
根据所需字段检查给定的属性值,在适当的地方生成缺失的字段错误。
根据所需字段检查给定的属性值,在适当的地方生成缺失的字段错误。
applyPropertyValues
将给定的属性值应用于目标对象。默认实现将所有提供的属性值应用为bean属性值。
将给定的属性值应用于目标对象。默认实现将所有提供的属性值应用为bean属性值。
AbstractPropertyAccessor.setPropertyValues
BeanWrapperImpl.setPropertyValue(PropertyValue pv)
执行到此,我们将值set到了实体Game中
执行到此,我们将值set到了实体Game中
获取参数名称
gameId
gameId
getBeanWrapperForPropertyPath(gameId);
对数据格式进行一些处理,详见此方法调用的
getFirstNestedPropertySeparatorIndex
并返回获取BeanWrapperImpl
它是一个bean的映射,其实就是Game类的映射
对数据格式进行一些处理,详见此方法调用的
getFirstNestedPropertySeparatorIndex
并返回获取BeanWrapperImpl
它是一个bean的映射,其实就是Game类的映射
getPropertyNameTokens
将属性名解析为一个属性名标记PropertyTokenHolder
将属性名解析为一个属性名标记PropertyTokenHolder
给PropertyValue的resolvedTokens属性赋值
setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv)
935行的方法
935行的方法
PropertyDescriptor pd = PropertyValue.resolvedDescriptor;
PropertyDescriptor类:(属性描述器)
JDK java.beans包下的一个类
JDK java.beans包下的一个类
从pd中获取该参数的readMethod
执行readMethod.invoke(Game)获取旧值
convertForProperty
这里获得了根据类型转换后的参数的值 1
这里获得了根据类型转换后的参数的值 1
new 了一个property类
BeanWrapperImpl.convertIfNecessary
convertIfNecessary
TypeConverterDelegate.convertIfNecessary
将指定属性的值转换为所需类型
将指定属性的值转换为所需类型
writeMethod.invoke(this.object, value);
执行setGameId方法写入值
object = Game , value = 1;
执行setGameId方法写入值
object = Game , value = 1;
validateIfApplicable
检查方法是否有Validated注解
检查方法是否有Validated注解
将Modelset到mavContainer中
doInvoke
执行方法,获取返回值returnValue
执行方法,获取返回值returnValue
ReflectionUtils.makeAccessible(getBridgedMethod());
将方法设置为可执行
method.setAccessible(true);
将方法设置为可执行
method.setAccessible(true);
getBridgedMethod().invoke(getBean(), args);
调用此方法也就是我们的controller方法
调用此方法也就是我们的controller方法
setResponseStatus
如果有responseStatus注解则设置返回响应值
如果有responseStatus注解则设置返回响应值
this.returnValueHandlers.handleReturnValue
RequestResponseBodyMethodProcessor.handleReturnValue
writeWithMessageConverters
将给定的返回值写入给定的web请求
将给定的返回值写入给定的web请求
getModelAndView
mavContainer.isRequestHandled()
这里会判断是否完全处理,若为true,则返回Null
这里会判断是否完全处理,若为true,则返回Null
applyDefaultViewName
mappedHandler.applyPostHandle
processDispatchResult
triggerAfterCompletion
resetContextHolders
requestAttributes.requestCompleted()
executeRequestDestructionCallback
单独启动一个线程执行请求完成后已注册执行的所有回调。
单独启动一个线程执行请求完成后已注册执行的所有回调。
updateAccessedSessionAttributes
publishRequestHandledEvent
OncePerRequestFilter.doFilter
0 条评论
下一页