Spring MVC 是如何建立在 Servlet API 之上的?

我们来探讨一下 Spring MVC 是如何建立在 Servlet API 之上的,看看它是怎样利用 Servlet API 的组件和机制来运作的:

  1. 核心入口点:DispatcherServlet 就是一个 HttpServlet

    • 这是最根本的联系。Spring MVC 的核心控制器 DispatcherServlet 直接或间接继承自 javax.servlet.http.HttpServlet
    • 这意味着 DispatcherServlet 拥有标准 Servlet 的所有生命周期方法(init(), service(), destroy())并且可以被 Servlet 容器(如 Tomcat)管理。
    • 如何集成:
      • web.xml (传统方式): 需要在 web.xml 文件中声明 DispatcherServlet 并为其配置 URL 映射(<servlet><servlet-mapping> 标签)。Servlet 容器启动时会读取这个配置,实例化 DispatcherServlet,并在匹配的 URL 请求到达时调用其 service() 方法。
      • Java 配置 : 通过实现 WebApplicationInitializer 接口(通常是继承 AbstractAnnotationConfigDispatcherServletInitializer),我们可以以编程方式ServletContext 注册 DispatcherServlet 实例及其映射。这利用了 Servlet 3.0+ 规范提供的 ServletContainerInitializer 机制,在容器启动时自动发现并执行你的配置类。这本质上是使用 Servlet API 提供的编程接口来替代 web.xml
    • 关键点: 无论哪种方式,最终都是 Servlet 容器根据 Servlet API 规范来加载、初始化并调用 DispatcherServlet
  2. 请求处理流程始于 Servlet API 对象

    • 当一个 HTTP 请求到达 Servlet 容器并被映射到 DispatcherServlet 时,容器会:
      • 创建 HttpServletRequest 对象,封装所有关于这个 HTTP 请求的信息(URL, 方法, 头, 参数, 请求体等)。
      • 创建 HttpServletResponse 对象,用于构建将要发送回客户端的 HTTP 响应。
      • 调用 DispatcherServletservice() 方法(或者根据 HTTP 方法调用 doGet(), doPost() 等),并将这两个 Servlet API 对象作为参数传入。
    • Spring MVC 的接管: DispatcherServlet 接收到这两个原始对象后,不会直接在自身代码中处理业务逻辑。它扮演的是**前端控制器(Front Controller)**的角色。
  3. 封装与抽象 HttpServletRequestHttpServletResponse

    • DispatcherServlet 内部会将原始的 HttpServletRequestHttpServletResponse 传递给它的协作组件(HandlerMapping, HandlerAdapter 等)。
    • 参数提取与绑定: Spring MVC 提供了强大的数据绑定机制。它会检查 Controller 方法的参数签名,并使用内部的 HandlerMethodArgumentResolver 实现来从 HttpServletRequest 中提取数据(如请求参数、路径变量、请求头、请求体)并将其转换、绑定到方法参数上(如 @RequestParam, @PathVariable, @RequestHeader, @RequestBody, 或直接绑定到 POJO)。这个过程隐藏了直接操作 HttpServletRequest.getParameter()request.getInputStream() 的复杂性
    • 响应构建: 同样,Controller 方法的返回值(如 String 代表视图名, ModelAndView, 或带有 @ResponseBody 的对象)会被 HandlerMethodReturnValueHandler 处理。最终,这些处理器会利用传入的 HttpServletResponse 来设置状态码、响应头,并将响应体(渲染后的 HTML、JSON/XML 数据等)写入 response.getOutputStream()response.getWriter()Spring MVC 提供了视图解析、消息转换等机制,简化了构建响应的过程
    • 直接访问(可选): 尽管 Spring MVC 提供了抽象,但如果你确实需要原始的 Servlet API 对象,可以直接在 Controller 方法参数中声明 HttpServletRequestHttpServletResponse,Spring 会自动将它们注入。
  4. 利用 ServletContext 存储应用上下文

    • Spring 框架(不仅仅是 Spring MVC)通常需要一个全局的应用上下文 (ApplicationContext) 来管理 Bean(如 Service, Repository 等)。对于 Web 应用,这通常是 WebApplicationContext
    • ContextLoaderListener 这是一个标准的 javax.servlet.ServletContextListener。通常配置在 web.xml 或通过 WebApplicationInitializer 注册。当 Servlet 容器初始化 Web 应用(创建 ServletContext)时,会触发这个 Listener 的 contextInitialized() 方法。
    • 作用: ContextLoaderListenercontextInitialized() 方法中创建 Spring 的根应用上下文 (Root WebApplicationContext),并将其存储为 ServletContext 的一个属性(通常使用 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE 作为键)。
    • 共享: 这样,DispatcherServlet(以及应用中的其他 Servlet 或 Filter)就可以通过 ServletContext.getAttribute() 方法访问到这个共享的根上下文,从而访问到整个应用共享的 Bean。
    • DispatcherServlet 通常还会创建自己的子上下文,包含与 Web 相关的 Bean(Controller, ViewResolver 等),这个子上下文可以访问根上下文中的 Bean。
  5. 利用 Servlet Filter 机制

    • Servlet API 提供了 Filter (javax.servlet.Filter) 机制,允许在请求到达 Servlet 之前或响应离开 Servlet 之后进行拦截和处理。
    • Spring 大量使用 Filter 来实现横切关注点:
      • CharacterEncodingFilter: 统一请求和响应的字符编码。
      • HiddenHttpMethodFilter: 支持在 HTML 表单中使用 PUT, DELETE 等方法。
      • Spring Security: 安全认证和授权的核心就是通过一系列 Filter Chain 实现的。
    • 这些 Filter 是标准的 Servlet Filter,它们的配置和生命周期管理都遵循 Servlet API 规范。它们在 DispatcherServlet 之前或之后处理 HttpServletRequestHttpServletResponse

总结来说,Spring MVC 建立在 Servlet API 之上的方式体现在:

  • 核心组件是 Servlet: DispatcherServlet 是一个标准的 HttpServlet
  • 遵循 Servlet 生命周期: DispatcherServlet 的加载、初始化和销毁由 Servlet 容器管理。
  • 接收 Servlet API 对象: DispatcherServlet 通过其 service 方法接收容器传入的 HttpServletRequestHttpServletResponse
  • 基于 Servlet API 对象进行抽象: Spring MVC 提供了更高级的 API 来访问请求数据和构建响应,但底层操作的仍然是 Servlet API 对象。
  • 利用 ServletContext: 通过 ServletContextListenerServletContext 属性来管理和共享 Spring 的 WebApplicationContext
  • 集成 Servlet Filter: 使用标准的 Servlet Filter 实现各种横切功能。

Spring MVC 巧妙地利用了 Servlet API 提供的基础构件和扩展点,在其上构建了一个功能丰富、结构清晰、易于使用的 Web 框架,大大提高了开发效率。它没有重新发明轮子,而是站在了巨人的肩膀上。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值