- 什么是 MVC? (核心概念)
- 为什么在 Java Web 中使用 MVC? (解决的问题)
- Java Web MVC 的经典工作流程 (请求的生命周期)
- Java Web MVC 的三大核心组件详解 (Model, View, Controller)
- Java Web MVC 的演进历史 (从 Servlet 到 Spring Boot)
- 一个简单的 MVC 示例 (代码演示)
- 总结与最佳实践
什么是 MVC?
MVC 是一种软件设计架构模式,它将一个应用程序划分为三个相互关联但又职责明确的部分:

-
Model (模型):
- 职责: 负责数据和业务逻辑,它是应用程序的核心。
- 数据库操作、业务规则计算、数据验证等,它不关心数据如何显示,也不关心用户如何与数据交互。
- 类比: 一个公司的“财务部门”或“研发部门”,负责处理核心业务和计算,但本身不直接面对客户。
-
View (视图):
- 职责: 负责数据显示,它是用户直接看到和交互的界面。
- HTML、JSP、Thymeleaf 模板、JSON/XML 数据等,它只负责展示从 Model 传递过来的数据,不包含任何业务逻辑。
- 类比: 公司的“前台”或“宣传册”,负责展示信息,但不知道这些信息是如何计算出来的。
-
Controller (控制器):
- 职责: 负责接收用户请求,协调 Model 和 View。
- 处理 HTTP 请求、调用 Model 的业务逻辑、从 Model 获取数据、选择合适的 View 并将数据传递给 View 进行渲染。
- 类比: 公司的“客服”或“经理”,接收客户(用户)的需求,协调后台部门(Model)处理,然后把结果(产品/数据)交给前台(View)展示给客户。
核心思想: 关注点分离,将数据、业务逻辑、用户界面分离开,使得代码结构更清晰、更易于维护、扩展和测试。

为什么在 Java Web 中使用 MVC?
在早期的 Java Web 开发中,如果没有 MVC,开发者常常会将 Java 代码(业务逻辑)和 HTML 代码(视图)混合在一起写在 JSP 文件中,这被称为“脚本式编程”(Scriptlet)。
这种方式带来了很多问题:
- 难以维护: 修改一个小的界面样式可能需要改动复杂的 Java 代码,反之亦然。
- 代码重用性差: 业务逻辑和视图紧密耦合,无法在其他地方复用。
- 测试困难: 无法单独测试业务逻辑,因为它和视图混在一起。
- 团队协作困难: 前端开发者需要懂 Java,后端开发者需要懂 HTML,协作效率低下。
MVC 架构完美地解决了这些问题,实现了前后端职责分离,成为 Java Web 开发的黄金标准。
Java Web MVC 的经典工作流程
当一个用户发起请求时,MVC 架构的处理流程如下:
- 用户发起请求: 用户在浏览器中输入 URL 或点击链接,向服务器发送一个 HTTP 请求。
- Controller 接收请求: 前端控制器(如
DispatcherServlet)接收到请求,并根据 URL 信息(如/user/list)将其分发给对应的 Controller 方法。 - Controller 处理请求: Controller 方法执行,它不直接处理业务,而是:
- 调用 Model 层的服务,请求处理业务逻辑(查询用户列表)。
- Model 层执行数据库操作,返回处理后的数据(一个包含用户信息的
List<User>对象)。
- Controller 选择视图: Controller 将 Model 返回的数据打包,并选择一个合适的 View(
user_list.jsp)。 - View 渲染数据: Controller 将数据和视图名称返回给前端控制器,前端控制器使用 View 技术(如 JSP)将数据渲染成最终的 HTML 页面。
- 响应返回用户: 渲染后的 HTML 页面作为 HTTP 响应,被发送回用户的浏览器,用户看到最终的页面。
Java Web MVC 的三大核心组件详解
Model (模型)
在 Java Web 中,Model 通常不是一个单一的类,而是由以下几部分组成:
-
POJO/Entity (Plain Old Java Object / 实体类): 也叫领域对象,与数据库表结构一一对应。
User.java,Product.java,它们只包含属性和 getter/setter 方法。// User.java (Entity) public class User { private Long id; private String username; private String email; // getters and setters... } -
Service (服务层): 负责核心业务逻辑,它调用 DAO 层来操作数据库,并封装复杂的业务规则。
UserService.java。// UserService.java (Service) @Service public class UserService { @Autowired private UserDAO userDAO; public List<User> getAllUsers() { // 可以在这里添加业务逻辑,比如过滤、排序等 return userDAO.findAll(); } } -
DAO (Data Access Object / 数据访问层): 负责与数据库进行直接交互。
UserDAO.java,在现代框架中,这部分通常被 MyBatis、JPA (Hibernate) 等框架替代。
View (视图)
View 的职责就是展示数据,在 Java Web 中,常见的视图技术有:
- JSP (JavaServer Pages): 早期的主流技术,允许在 HTML 中嵌入 Java 代码,现在已不推荐,但很多老项目仍在使用。
- Thymeleaf: 现代化的服务器端模板引擎,语法更优雅,与 HTML 完全兼容,可以直接在浏览器中预览模板。
- FreeMarker: 另一个流行的模板引擎。
- JSON/XML: 在开发 RESTful API 时,View 层可能不需要渲染 HTML,而是直接将数据序列化为 JSON 或 XML 格式返回给前端(由前端框架如 Vue/React 渲染)。
Controller (控制器)
Controller 是整个流程的指挥官,在 Java Web 中,Controller 的实现方式也经历了演变:
-
原生 Servlet: 最基础的控制器,开发者需要自己编写
doGet()和doPost()方法,手动处理请求、调用业务逻辑、选择视图,非常繁琐。 -
Spring MVC Framework: 使用
@Controller注解标记一个类为控制器,方法通过@RequestMapping或@GetMapping/@PostMapping等注解来映射 URL。@Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @GetMapping("/list") public String listUsers(Model model) { List<User> users = userService.getAllUsers(); // 将数据存入 Model 对象,key 为 "users" model.addAttribute("users", users); // 返回视图名称,框架会解析为 "WEB-INF/views/user_list.jsp" return "user_list"; } } -
Spring Boot: 在 Spring MVC 的基础上,通过自动配置和约定优于配置,极大地简化了开发,控制器写法与 Spring MVC 几乎一样,但配置工作大大减少。
Java Web MVC 的演进历史
理解这个演进过程,能帮助你更好地把握 Java Web 开发的脉络。
-
第一阶段:Model 1 (JSP + JavaBean)
- 特点: JSP 既负责视图展示,又包含少量 Java 代码处理请求,JavaBean (Model) 只负责数据封装。
- 问题: JSP 职责过重,代码混乱,难以维护。
-
第二阶段:Model 2 (MVC 模式的雏形)
- 特点: 引入了 Servlet 作为控制器,Servlet 处理请求和业务逻辑,然后转发给 JSP 进行渲染,JavaBean 作为 Model。
- 意义: 这是 MVC 模式在 Java Web 中的首次实践,实现了初步的职责分离,但每个 Servlet 都需要手动配置,开发效率不高。
-
第三阶段:框架化 MVC (Struts, Spring MVC)
- Struts 1/2: 一个成熟的 MVC 框架,通过配置文件(如
struts.xml)定义 Action(控制器)和视图的映射,它极大地规范了开发,但也带来了复杂的配置和僵化的设计。 - Spring MVC: 作为 Spring 框架的一部分,它更灵活,更符合 Java 开发习惯,通过注解(如
@Controller)来简化配置,成为企业级应用开发的事实标准。
- Struts 1/2: 一个成熟的 MVC 框架,通过配置文件(如
-
第四阶段:现代 MVC (Spring Boot)
- Spring Boot: 不是要取代 Spring MVC,而是为了让 Spring MVC 的开发变得“开箱即用”,它通过自动配置、内嵌服务器(如 Tomcat)和起步依赖,让开发者可以专注于业务逻辑本身,而不用关心繁琐的配置。Spring Boot + Spring MVC 是 Java Web 开发的主流和首选方案。
一个简单的 MVC 示例 (基于 Spring Boot)
假设我们要实现一个功能:访问 http://localhost:8080/hello,页面显示 "Hello, Spring MVC!"。
项目结构
src/main/java/
└── com/example/demo/
├── DemoApplication.java // 启动类
├── controller/
│ └── HelloController.java // 控制器
├── model/
│ └── Message.java // 模型 (简单POJO)
└── DemoApplication.java
src/main/resources/
└── templates/
└── hello.html // 视图 (Thymeleaf模板)
Model (Message.java)
package com.example.demo.model;
public class Message {
private String text;
public Message(String text) {
this.text = text;
}
public String getText() {
return text;
}
}
View (hello.html)
使用 Thymeleaf 模板引擎,文件放在 src/main/resources/templates 目录下。
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">Hello Page</title>
</head>
<body>
<h1 th:text="${message.text}">Default Message</h1>
</body>
</html>
th:text="${message.text}"是 Thymeleaf 的语法,表示将 Model 中名为message的对象的text属性值渲染到这里。
Controller (HelloController.java)
package com.example.demo.controller;
import com.example.demo.model.Message;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HelloController {
@GetMapping("/hello")
public String sayHello(Model model) {
// 1. 创建 Model 对象
Message message = new Message("Hello, Spring MVC!");
// 2. 将 Model 对象添加到 Spring 的 Model 中
// "message" 是在视图中引用的 key
model.addAttribute("message", message);
// 3. 返回视图名称,框架会自动解析为 "hello.html"
return "hello";
}
}
启动类 (DemoApplication.java)
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
运行流程:
- 启动
DemoApplication。 - 浏览器访问
http://localhost:8080/hello。 DispatcherServlet(Spring Boot 自动配置) 收到请求,根据/hello找到HelloController的sayHello方法。sayHello方法创建Message对象,并通过model.addAttribute将其存入Model。- 方法返回字符串
"hello"。 ViewResolver(视图解析器) 将"hello"解析为src/main/resources/templates/hello.html。- Thymeleaf 引擎渲染
hello.html,将${message.text}替换为 "Hello, Spring MVC!"。 - 最终的 HTML 页面被发送回浏览器并显示。
总结与最佳实践
- 核心是分离: MVC 的核心思想是关注点分离,始终牢记 Model、View、Controller 各自的职责,不要越界。
- Controller 越薄越好: Controller 只负责请求路由和参数校验,复杂的业务逻辑应该交给 Service 层(Model)处理。
- View 不包含逻辑: 视图模板中不应该出现复杂的业务逻辑判断,只负责数据展示,复杂的逻辑应该在 Controller 或 Service 中处理好再传递给 View。
- 拥抱现代框架: 对于新项目,直接使用 Spring Boot + Spring MVC + Thymeleaf/REST 的组合,这是最高效、最主流的方案。
- RESTful API: 当开发前后端分离的应用时,Controller 通常不返回视图名称,而是直接返回 JSON 数据,View 层由前端框架(如 Vue.js, React)负责,Controller 的写法略有不同,使用
@ResponseBody或@RestController。@RestController @RequestMapping("/api/users") public class UserApiController { @GetMapping public List<User> listUsers() { return userService.getAllUsers(); } }
希望这份详细的指南能帮助你彻底理解 Java Web 开发中的 MVC 架构!
