SpringMVC框架源码解析之一:核心组件和执行流程
SpringMVC框架这几年可以说是java语言中最热门的MVC框架了。在前后端分离的时代,就算不使用它来处理前端页面,但也是用它来提供Restful API。
Servlet的生命周期
在开始了解SpringMVC框架之前,先来了解下servlet生命周期:
public interface Servlet {
//应用容器(如tomcat)调用init方法,传入ServletConfig,来初始化servlet
public void init(ServletConfig config) throws ServletException;
...
//应用容器获取到http请求后,调用service方法对请求进行处理
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
...
//应用容器调用destroy方法,来销毁servlet
public void destroy();
}
可以看到,servlet是在应用容器(如tomcat)中生存的,其生命周期由应用容器来管理。
servlet的init() 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用,它可以配置成在容器启动时触发,也可以在第一次处理客户请求时初始化。
servlet的service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。
servlet的destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。
下图显示了一个典型的 Servlet 生命周期:
- 第一个到达服务器的 HTTP 请求被委派到 Servlet 容器。
- Servlet 容器在调用 service() 方法之前加载 Servlet。
- 然后 Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的 Servlet 实例的 service() 方法。
SpringMVC核心组件介绍
- DispatcherServlet,这个Servlet会接受所有的请求,是整个框架的控制中心,负责整体执行逻辑的控制,它会将具体的工作交由具体的其他组件来实现。
- HandlerMapping,这个组件用来注册和查询url和处理器映射关系,即DispatcherServlet接受到了一个请求后,听过这个组件来决定使用哪个handler来处理。
- HandlerAdapter,这个组件用来适配各种各样的handler形式,比如实现Controller接口形式的处理器,实现HttpRequestHandler接口形式的处理器,使用@RequestMapping注解的方法,甚至另外一个servlet。
- Handler,就是我们实现的控制器。
- ModelAndView,这个组件用来封装模型数据和视图。
- ViewResolver,视图解析器,用来将一个视图名称解析成一个view对象
- View 视图,其作用是将模型数据和视图模板渲染出来,并输出到response中。
Spring MVC的执行流程
一次HTTP请求的旅行:
- 客户端发起HTTP请求到servlet容器,如tomcat,servlet容器将请求交到DispatchServlet去处理
- DispatchServlet拿到请求后,解析出请求的url,然后找HandlerMapping去获取这个请求要处理的handler。
- HandlerMapping返回HandlerExecutionChain,它会封装具体的handler和拦截器
- DispatchServlet通过handler去找对应的HandlerAdapter
- 调用HandlerAdapter,其内部会调用具体的handler,执行具体的业务逻辑
- HandlerAdapter获取具体的handler执行结果,返回ModelAndView
- DispatchServlet获取HandlerAdapter返回的ModelAndView
- DispatchServlet通过ModelAndView去找ViewResolver解析出一个真实的view对象(逻辑视图到实际视图)
- DispatchServlet获取解析出来的View对象
- DispatchServlet通过View去渲染response返回结果。