Spring MVC(一)

       在SpringBoot中MVC初始化主要由DispatcherServletAutoConfiguration及WebMvcAutoConfiguration完成。DispatcherServletAutoConfiguration会向Spring容器中注册DispatcherServlet,并且使用ServletRegistrationBean动态的把DispatcherServlet添加到Servlet容器中,这样就无需手工编辑web.xml文件。

       WebMvcAutoConfiguration则是初始化MVC所需对象,默认情况下Spring MVC是通过WebMvcAutoConfiguration自动初始化。还可以可以手工使用@EnableWebMvc,但这并不常用,两者只会生效一个。在还没有SpringBoot的时候,通常都是通过在XML文件中配置<mvc:annotation-driven />开启,AnnotationDrivenBeanDefinitionParser会解析引标签并注册默认对象。

       在之前有遇到过一个MVC多次初始化的问题,那时项目组同事从Github上找到一个好用的Excel导出导入工具,该工具基于SpringBoot及MVC实现。原理也很简单,就是通过自定义SpringMVC的HandlerMethodArgumentResolver及HandlerMethodReturnValueHandler来处理入参及出参。该同事在自己写的Demo中运行良好,但一加入到项目中则不生效,刚开始还怀疑是否是这个插件有问题,还笑称5颗星的项目不靠谱(PS:该插件在Github上Star数只有5)。MVC启动的时候该插件相关的Bean也正常启动,因为该插件相关的Handler类是在RequestMappingHandlerAdapter中调用,所以通过断点调试RequestMappingHandlerAdapter的启动流程,发现该Bean被初始化了两次,一次包含了自定义的Handler,一次则没有,而最后生效的则是那个没有包含自定义Handler的RequestMappingHandlerAdapter。通过不断的往上查找才找到了罪魁祸首,原来MVC分别被WebMvcAutoConfiguration及AnnotationDrivenBeanDefinitionParser初始化了两次,查找项目Spring相关的XML配置文件果然发现添加了<mvc:annotation-driven />,把该标签去掉则正常了。也不知道该配置是什么时候加上去的,要说为什么在SpringBoot中还会有用XML配置的方式,我想应该是历史遗留问题吧。

       DispatcherServlet是SpringMVC的入口,继承了FrameworkServlet,来看看它的启动流程。在FrameworkServlet的initServletBean方法中,会创建一个WebApplicationContext(MVC容器,默认为XmlWebApplicationContext)作为Spring容器的子容器,并在configureAndRefreshWebApplicationContext方法中启动该容器,最后调用onRefresh(在DispatcherServlet重写了该实现)。在DispatcherServlet.onRefresh中实例化并关联了容器中的MultipartResolver、LocaleResolver、ThemeResolver、HandlerMappings、HandlerAdapters、HandlerExceptionResolvers、RequestToViewNameTranslator、ViewResolvers、FlashMapManager。

       当一个请求进来,会在DispatcherServlet.doDispatch中进行分发、前后、返回结果及异常处理,流程如下:

           1、首先检查是否包含了上传文件,如果是则对Request进行包装并替换。默认为StandardMultipartHttpServletRequest。

           2、获取到对应的HandlerExecutionChain,以及HandlerAdapter。

           3、调用HandlerExecutionChain.applyPreHandle进行前置处理。

           4、调用HandlerAdapter.handle进行请求处理。

           5、调用HandlerExecutionChain.applyPostHandle进行后置处理。

           6、在processDispatchResult方法中处理返回结果或异常。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值