springMvc的流程梳理
2020-08-31 16:33:36 3 举报
springMvc
作者其他创作
大纲/内容
RequestMappingInfoHandlerMapping
this.handlerMappings该类初始化的时候完成写入的.WebMvcConfigurationSupport这个类中声明了一系列的Handler
不同的参数解析器。会有不同的参数解析结果。本质就是获取到参数的名称和注解。再去逐层判断拿到arg的值
wac.refresh();
在拿到Controller的执行调用结果以后。需要的是完成一个返回值的解析操作。这里会有15种
在创建HandlerMathod的时候写进去的参数信息们
WebMvcConfigurerAdapter实现类的addInterceptors(InterceptorRegistry registry)
继承
HttpServletBean
错误的方式.也不算错误.我们通常启动用的不是这种而已
StandardContext
BEST_MATCHING_HANDLER_ATTRIBUTE--->bestMatch.handlerMethodPATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE--->lookupPathURI_TEMPLATE_VARIABLES_ATTRIBUTE--->uriVariables
span style=\"font-size: inherit;\
有了参数。有了方法就可以执行反射调用了doInvoke(args)
2.ContextLoaderListener listener = new ContextLoaderListener(rootAppContext)3.servletContext.addListener(listener);
uriTemplateVars.get(name)从集合中拿到值
url-MappingInfo(请求地址和注解对象urlLookup)mappingInfo-HandlerMethod(注解和方法mappingLookup)handlerMethod-corsConfig(方法和跨域对象corsLookup)
2.通过HandlerMethod匹配的HandlerAdapter对象 getHandlerAdapter(mappedHandler.getHandler());
通过类找到他的所有方法,开始循环mc.doWith(method);调回上层的lambda metadataLookup.inspect(specificMethod);调回上层的lambda
ViewNameMethodReturnValueHandler---处理视图的jsp
1.createServletApplicationContext()
afterPropertiesSet()
这里根据HandlerMethod去寻找对应的Adapter(策略模式)这个集合是在初始化的时候添加进来来的handlerAdapters
getBean()this.bean;
1.把HandlerMethod对象包装到HandlerExecutionChain对象中主要是会进一步封装添加拦截器2.将之前的HandlerInterceptor挨个匹配加进去(matches操作)
1.getHandler(processedRequest)
info = typeInfo.combine(info);
1.createRootApplicationContext();
方法内会根据请求类型进行相应的跳转
2.循环调用initializer.onStartup(servletContext);
策略模式,根据parameter能否找到对应参数的处理类,能找到就返回true都没有就抛出异常this.resolvers.supportsParameter(parameter)
这个是用来解析/{AAA}/{BBB} 的抽象父类1.AbstractNamedValueMethodArgumentResolver在这个实现里面先获取参数值。注解信息调用真正的本类
1.创建spring上下文,注册了SpringContainer2.创建监听器3.将监听器写入servlet上下文
通过这个servlet的新规范。就可以完美的省略了web.xml的配置。接下来想办法简化springmvc.xml中的各个标签
计数器加一调用下一个
现在对象都已经准备好了。还差一个调用refresh的时机,这个时机就是ContextLoaderListener的contextInitialized
1.调用了一个钩子方法。找到要扫描的类2.创建上下文环境对象AnnotationConfigWebApplicationContext3. context.register(configClasses);//和spring初始化的对象一样
configureAndRefreshWebApplicationContext(cwac);
1.调用了一个钩子方法。找到要扫描的类2.创建上下文环境对象AnnotationConfigWebApplicationContext3. context.register(configClasses);//和spring初始化的对象一样 (和上面一样)
getInterceptors()
new UriTemplateVariablesHandlerInterceptor()
判断是否有跨越请求。对跨域请求头进行一个匹配,之后如果有就设置跨域处理的拦截器。
processCandidateBean(beanName);
1.循环类中所有的方法2.收集@RequestMapping注解信息合并类和方法的url3.建立method对象和对应的RequestMappingInfo注解信息对象的映射关系4.创建HandlerMethod对象。封装了method。beanName,注解。参数等等信息,包括没初始化的还有beanfactory对象5.建立RequestMappingInfo和HandlerMethod的映射关系6.建立url和RequestMappingInfo对象的映射关系
从servletContext中使用ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE拿到了容器,并在下面创建了父子的关系即servlet为子容器
initWebApplicationContext()初始化容器
AbstractHandlerMethodMappinggetHandlerInternal(request);
表示初始化
onStartup(ServletContext servletContext)
registerContextLoaderListener(servletContext);注册监听器
2.getNamedValueInfo(parameter);
@Import(DelegatingWebMvcConfiguration.class)
RequestMappingHandlerAdapter
为调用方法设置各种值...
wac.refresh()
Tomcat中的类
RequestMappingHandlerAdapter完成了@ModelAttribute注解的方法//设置参数解析器//设置返回值解析器等各种参数的设置
建立uri和method的映射关系detectHandlerMethods(beanName);
1.getUrlPathHelper().getLookupPathForRequest(request);
spring-web的开始,tomcat会收集这个注解中配置的类。并封装成set集合。在启动的时候for循环调用ServletContainerInitializer的onStartup@HandlesTypes(WebApplicationInitializer.class)
startInternal()
会涉及到两个比较重要的AbstractContextLoaderInitializer //这个类似于web.xml中的ContextLoaderListener的注册AbstractDispatcherServletInitializer //这个是web.xml 中的dispactcherServlert的注册
initHandlerMethods();
建立的三个缓存
这个值会在这里用到
handler.supportsReturnType(returnType)匹配策略参数,返回对应的handler
//根据参数获取对应参数的解析类getArgumentResolver(parameter);
adapter.supports(handler)根据supports结果返回对应的Adapter
getServletMappings()也是一个钩子方法。调用到子类的实现中。用来获取dispatcherServlet的拦截映射信息
AbstractContextLoaderInitializer
@EnableWebMvc
入参的包装类,里面包装了参数类型,参数名称,参数注解等等信息getMethodParameters();
HttpServelt
。。。。很多@bean的实现
url-MappingInfo(请求地址和注解对象urlLookup)mappingInfo-HandlerMethod(注解和方法mappingLookup)回顾一下之前有缓存的两个Map
否
这是一条钩子链条。通过调用实现类中的方法来获取自定义的组件
Controller具体方法的调用。根据拿到的Adapter调用对应的handle方法
先判断缓存中是否有,没有的话for循环去找对应的解析器methodArgumentResolver.supportsParameter(parameter)
这个对象封装了bean,beantype,method,parameters等等信息。另外值得注意的是可能controller还没有进行完实例化。这时候会吧beanfactory传进来
initWebApplicationContext(event.getServletContext()
DispatcherServlet
registration.setLoadOnStartup(1); registration.addMapping(getServletMappings()); registration.setAsyncSupported(isAsyncSupported());
RequestMappingHandlerMapping
查找注解isHandler(beanType)
1.使用建造者模式构建config对象RequestMappingInfo.BuilderConfiguration()2. super.afterPropertiesSet();
dispatcherservlet会先调父类的
1.查url和RequestMappingInfo缓存this.mappingRegistry.getMappingsByUrl(lookupPath);
1.创建springmvc的上下文,注册了MvcContainer类2.创建dispatcherServlet3.加入servlet上下文中4.设置一些属性
符合servlet规范。HttpServletBean初始化的时候会调用init()方法
contextInitialized(ServletContextEvent event)
1.实例化WebApplicationInitializer对象
创建RequestMappingInfo对象createRequestMappingInfo(method)
for循环调用扫描到的ServletContainerInitializer的实现类
initServletBean();通过他转发给他的子类FrameworkServlet
先收集了方法上的。之后收集类上的在进行一个合并操作。如果没有就返回null如果有就建立方法对象和注解封装对象的映射关系(methodMap )
mapping.getHandler(request);
SpringServletContainerInitializer
其中之一PathVariableMapMethodArgumentResolver
类实例化的时候会进行init操作
AbstractUrlHandlerMapping
AbstractDispatcherServletInitializer
FrameWorkServlet
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
addInterceptors(registry);
这里可以注意的是调用顺序是一个倒叙调用for (int i = interceptors.length - 1; i >= 0; i--) 这里倒序,前置的是正序。(至于为什么有点没想清楚)可能只是为了
registerDispatcherServlet(servletContext);注册servlet
这个类可不得了,他继承自WebMvcConfigurationSupport这个类里有很多的@bean注解把,传统xml解析才会生成的对象都给生成了,实现了InitializingBean接口。然后重写了afterPropertiesSet()方法然后逐步完成了DispatcherServlet中所需要组件的初始化的各种操作
2.createDispatcherServlet(servletAppContext)
0 条评论
下一页