Spring MVC 如何体现 Model-View-Controller 各自的职责?它们之间是如何协作的?

Spring MVC 中的组件与 MVC 角色的对应:

  1. Controller (控制器):

    • 体现: 主要由我们开发时编写的带有 @Controller@RestController 注解的 Java 类及其内部的方法(通常称为 Handler 方法)来体现。
    • 职责:
      • 接收请求: 通过 @RequestMapping 及其变体 (@GetMapping, @PostMapping 等) 注解,将特定的 HTTP 请求(URL、HTTP 方法、参数等)映射到对应的 Handler 方法。DispatcherServlet 会根据 HandlerMapping 的结果找到这个 Controller 方法。
      • 处理用户输入: 解析请求中的数据,如查询参数 (@RequestParam)、路径变量 (@PathVariable)、请求体 (@RequestBody)、表单数据等,并将它们绑定到方法的参数上。
      • 调用业务逻辑 (与 Model 交互): 调用注入的 Service 层或其他业务逻辑组件来执行实际的业务操作、数据处理或数据获取。
      • 准备模型数据: 将处理结果或需要展示的数据(即 Model 数据)封装起来,以便传递给 View。这通常通过向方法参数中的 Model 对象添加属性,或者构建并返回一个 ModelAndView 对象来实现。
      • 选择视图: 返回一个逻辑视图名(String 类型),或者返回一个包含逻辑视图名和模型数据的 ModelAndView 对象。对于 RESTful 服务 (@RestController 或方法上使用 @ResponseBody),Controller 直接返回需要序列化的对象(如 POJO),此时响应体本身扮演了视图的角色。
  2. Model (模型):

    • 体现: 在 Spring MVC 中,Model 的体现是多方面的:
      • 数据载体 (Data Carrier): 最直接的体现是 Controller 传递给 View 的数据。Spring MVC 提供了 Model 接口(及其实现如 ModelMap)或 ModelAndView 类来充当这个数据容器。我门将需要展示的数据放入这些容器中。
      • 业务状态与逻辑 (Business State & Logic): 更深层次上,Model 代表了应用程序的核心。这通常是 Controller 调用的 Service 层和 Repository/DAO 层 Bean。这些 Bean 封装了业务规则、数据持久化逻辑以及应用程序的状态。Controller 与这些 Bean 交互来读取或修改应用状态。
      • 领域对象 (Domain Objects): Controller 处理或传递的普通 Java 对象(POJO),如 User, Product, Order 等,它们代表了业务领域中的实体。
    • 职责:
      • 封装数据: 持有需要传递给视图的数据(通过 ModelModelAndView)。
      • 执行业务逻辑: Service/Repository 层负责处理业务规则、数据验证、与数据库交互等核心任务。
      • 维护应用状态: 代表了应用程序当前的数据状态。
  3. View (视图):

    • 体现:
      • 视图模板: 各种模板引擎的文件,如 JSP 文件、Thymeleaf 模板 (.html)、Freemarker 模板 (.ftl) 等。
      • Spring 的 View 接口: Spring MVC 定义了一个 View 接口,以及针对不同视图技术的具体实现(如 JstlView, ThymeleafView)。ViewResolver 负责将逻辑视图名解析为具体的 View 实例。
      • 直接响应内容: 对于 RESTful 服务,由 HttpMessageConverter(如 Jackson 处理 JSON)将 Controller 返回的对象序列化后的内容(JSON, XML 等)也可以看作是一种特殊的视图。
    • 职责:
      • 呈现数据: 获取 Controller 传递过来的模型数据(从 ModelModelAndView 中提取)。
      • 渲染用户界面: 使用模型数据填充视图模板,生成最终的 HTML、JSON、XML 或其他格式的响应内容,呈现给用户。
      • 不包含业务逻辑: 视图应该尽量保持简单,只负责展示逻辑。

它们之间的协作流程 (由 DispatcherServlet 驱动):

  1. 请求入口: HTTP 请求到达 DispatcherServlet
  2. 寻找处理器: DispatcherServlet 查询 HandlerMapping,根据请求信息(URL, HTTP Method 等)找到能够处理该请求的 Controller 方法 (Handler)。
  3. 适配与调用: DispatcherServlet 通过 HandlerAdapter 来调用选定的 Controller 方法。HandlerAdapter 负责处理方法参数的解析和数据绑定(例如,将请求参数注入到 @RequestParam 标记的参数,将 JSON 请求体反序列化到 @RequestBody 标记的对象)。
  4. Controller 处理: Controller 方法执行:
    • 接收解析后的请求数据。
    • 调用 Service 层等(与 Model 交互)执行业务逻辑。
    • 将结果数据放入 Model 对象(或 ModelAndView)。
    • 返回逻辑视图名(String)或 ModelAndView 对象(或直接返回数据对象给 @ResponseBody)。
  5. 视图解析 (非 @ResponseBody): 如果 Controller 返回的是逻辑视图名或 ModelAndViewDispatcherServlet 会将逻辑视图名交给 ViewResolver
  6. 获取具体视图: ViewResolver 根据逻辑视图名解析得到具体的 View 实例(例如,一个指向特定 JSP 文件的 JstlView 对象)。
  7. 数据渲染: DispatcherServlet 将 Controller 准备好的 Model 数据传递给 View 实例。View 实例使用这些数据渲染最终的响应(例如,JSP 引擎执行 JSP 文件并生成 HTML)。
  8. REST 响应 (@ResponseBody): 如果 Controller 方法使用了 @ResponseBody 或属于 @RestControllerHandlerAdapter 会使用合适的 HttpMessageConverter 将返回的对象序列化 为特定格式(如 JSON)并直接写入响应体。此过程通常跳过 视图解析和 View 渲染步骤。
  9. 响应返回: DispatcherServlet 将最终生成的响应(渲染后的 HTML 或序列化后的数据)返回给客户端。

通过这种方式,Spring MVC 利用 DispatcherServlet 作为前端控制器,协调 HandlerMapping, HandlerAdapter, Controller, Model, ViewResolver, View 等组件,清晰的实现了 MVC 模式的功能分离,使得我们在开发时可以专注于各自的部分,构建出易于维护的 Web 应用程序。

相关推荐
星辰烈龙3 小时前
黑马程序员Java基础9
java·开发语言
山沐与山3 小时前
【Redis】Redis集群模式架构详解
java·redis·架构
ss2733 小时前
Java并发编程:DelayQueue延迟订单系统
java·python·算法
wcy_10113 小时前
七大软件设计原则
java·设计规范
invicinble3 小时前
jar包在执行的时候需要关注的细节(提供一个解构jvm问题的视角)
java·jvm·jar
麦芽糖02193 小时前
SSE介绍及使用(Server-Send Events)
java
alan07213 小时前
【Java + Elasticsearch全量 & 增量同步实战】
java·elasticsearch·jenkins
hashiqimiya4 小时前
后端springboot的接收前端发来的数据反序列化原理
java
cat三三4 小时前
java之异常
java·开发语言
浙江第二深情4 小时前
前端性能优化终极指南
java·maven