前言
Spring MVC 框架使用了其”模型-视图-控制器”( Model-View-Controller )架构方式,用于开发灵活且松散耦合的 Web 应用程序。我们都使用过 SpringMVC 来处理信息,并渲染视图到 Browser。但需要注意的是,在现在的架构中,大都采用了前后端分离的情况,而我们在使用 SpringMVC 的时候,只需要关注 M(Model),C(Controller)这两个部分,而视图渲染的部分则交给了前端。
流程图
源码解析
(1):用户向服务发送 HTTP 请求,DispatcherServlet 捕获请求。
(2):DispatcherServlet 根据 URL,调用 HandlerMapping 获得该 Handler 对象以及所对应的拦截器,其返回的是 HandlerExecutionChain 对象,这个对象中就包含了 Handler 对象以及这个 Handler 所对应的拦截器。
(3):DispatcherServlet 根据获得的 Handler,选择一个合适的 HandlerAdapter 。(附注:如果成功获得 HandlerAdapter 后,此时将开始执行拦截器的 preHandler 方法),然后获取 Request 请求数据,填充 Handler,执行 Handler。
(4):上一步获取到 HandlerAdapter 后,会执行 Handler,并返回 ModelAndView
(5):根据返回的 ModelAndView ,选择一个适合的 ViewResolver(必须是已经注册到 Spring 容器中的 ViewResolver),解析出 View 对象,然后返回给 DispatcherServlet。
(6):ViewResolver 通过 render()方法结合 Model 和 View,来渲染视图。
(7):ViewResolver 通过 render()方法写回给 Browser。
流程详解
看完以上没有看过源码的童靴可能会一脸懵逼,此上也是围绕流程图进行了部分截取,方便大家理解,下面我们来搭建一个测试 Demo 来进一步了解。
(1):测试 Controller(模拟用户真实情况)
(2):在解析 DispatcherServlet 之前,我们先来看一下 DispatcherServlet 的父类 FrameworkServlet。
(3):通过上图我们不难看到一些敏感内容,如 doGet(…)、doPost(…)、doPut(…)、doDelete(…)等等,我们通过这些方法可以看到,这些方法都指向了同一个方法,processRequest(…)
(4):我们来看一下 FrameworkServlet 的 service(…)方法。
1 | protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
(5):我们来看一下父类 HttpServlet 所包含的方法。
(6):通过 service(…)我们可以看出,此方法是根据方法类型,分发请求的。
(7):我们继续跟进方法,就不难发现这些请求处理的方法就回到了(3)中所示。
(8):我们重点关注一下,processRequest(…)方法,(代码已作删减)
1 |
|
(9):通过上述代码,请求处理 doService(…)方法。我们可以看到父类中是一个抽象方法,Spring 中很多地方运用了这种方法,由父类抽象流程,交由子类在实现具体的方法,看到这里也就明白了,这个地方就是 DispatcherServlet 的入口方法,
(10):DispatcherServlet 中 doService(…)方法
1 | protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { |
(11):请求处理,DispatcherServlet 核心方法。
1 | protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { |