深入了解 Spring 框架之 WebMVC 框架
一. 概述
在常规情况下,我们都是用 spring 来做 web 服务;那么 web 的运行机制是什么样的?我们定义接口时都是通过添加 @Controller 注解,以及方法上面添加 @RequestMapping 注解来对外提供这样的接口,那么他们的底层原理又是什么样子的?从服务器接收到请求,又是怎么流转到 @RequestMapping 所标注的方法中去呢?流转过程中,都经历过哪些关键的类呢?我们带着这些问题去看 webmvc 框架。我们基于 spring boot 框架的源码进行解读,方便于我们更加方便了解 webmvc 框架的运行机制;
二. Servlet 容器
spring-boot 工程默认采用的 Tomcat 服务器;
ServletWebServerFactoryConfiguration 当检测到 Servlet 类存在时,说明时采用 Servlet 容器,就会向容器中注入 TomcatServletWebServerFactory 实例,该类创建 Tomcat 服务器的工厂类。DispatcherServletAutoConfiguration 类当检测到 DispatcherServlet 类的存在时,会向 ServletContext 容器中注册 DispatcherServlet;特别说明的是 DispatcherServlet 是单例。
有关 Filter 注入以及 Servlet 注入,可以参阅Tomcat 架构的认知。
有关 Tomcat 的配置信息,可以查阅 ServerProperties 类结构;
三. DispatcherServlet
在请求过来时,默认用该类进行处理请求的;该类有几大属性成员,如下图:
handlerMapping 用来处理不同请求所对应的处理器
handlerAdapters 该属性是用来做适配器用的,在这过程中,先执行拦截器在执行 Handler 所执行的逻辑,以及对 Handle 中注入所需要的对象;
handlerExceptionResolvers 用来处理 handlerMapping 的异常捕获处理。
时序图:
1. HandlerMapping 家族
HandlerMapping 下有很多实现类;如静态资源请求的,会交给 SimpleUrlHandlerMapping 子类来处理;
如 RequestMappingHandlerMapping 就是收集了在业务代码中含有 @Controller 注解以及 @RequestMapping 标注的对象。在 spring 中对标注 @RequestMapping 注解的方法进行封装成 HandlerMethod 对象;我们留意到 HandlerMethod 对象的子类中所包含的属性成员,其中里面几个很关键的属性:
WebDataBinderFactory 有关数据绑定的工厂;
HandlerMethodArgumentResolverComposite 会将请求报文中的数据进行解析从而封装成方法入参的类型,传给方法中;在业务代码开发中,我们常用的 @RequestBody 等注解
HandlerMethodReturnValueHandlerComposite 会将方法的运行结果,按照给定的形式返回给上游系统;
我们查看 HandlerMethodArgumentResolver 接口提供的实现类,就可以看到 spring 中都提供了哪些类型入参的解析;HandlerMethodReturnValueHandler 接口提供的实现类,就可以看到 spring 是如何对返回的对象如何返回到上游的系统;
2. HandlerAdapter 家族
3. HandlerExceptionResolver 家族
该接口是用来捕获 Handler 运行时异常;在我们常规开发中设计全局异常捕获时所使用的的 @ControllerAdvice 类以及方法中添加 @ExceptionHandler 时就是由 ExceptionHandlerExceptionResolver 自动从 spring 容器中检测出来的;
4. WebMvcConfigurationSupport 家族
在 springWebMVC 中提供了主要的入口对 MVC 进行配置的;其主要的入口是 WebMvcConfigurationSupport 该类;在我们常规开发中,如对序列化,以及校验器等配置都通创建一个实现 WebMvcConfigurer 接口的实现类即可达到配置效果;
四. 总结
大体讲述了 springwebmvc 的大体时序图,知道 webmvc 的运行机制;以及罗列了 webmvc 所涉及的关键类,他们是如何写作等;后续后逐步完善,有关 @RequestMapping 所标注的方法是如何封装成 HandlerMethod 的;以及 @ExceptionHandler 等;
评论