MVC 设计思想
MVC 是三个单词的首字母缩写,它们是 Model(模型)、View(视图)和 Controller(控制)。
这个模式认为,程序不论简单或复杂,从结构上看,都可以分成三层:
- 最上面的一层,是直接面向最终用户的”视图层”(View)。它是提供给用户的操作界面,是程序的外壳。
- 最底下的一层,是核心的”数据层”(Model),也就是程序需要操作的数据或信息。
- 中间的一层,就是”控制层”(Controller),它负责根据用户从”视图层”输入的指令,选取”数据层”中的数据,然后对其进行相应的操作,产生最终结果。
三层划分只是 MVC 的静态面貌。真正让它成为”思想”而非”目录结构”的,是依赖方向与变化隔离:View 与 Model 互不直接依赖,Controller 做中间调度,于是”界面变化”与”数据/业务变化”可以独立演进。本文补上交互流程、Spring MVC 的落地映射、以及 MVC 的变体与误用。
交互流程:一次请求的三角关系
经典 MVC 的交互(以 Web 应用为例):
- 用户操作 View(提交表单/点击链接)→ 请求进入 Controller
- Controller 解析意图,调用 Model 完成业务与数据操作
- Model 状态变化后,View 获取新状态渲染(Web 中简化为 Controller 选视图并填充模型数据)
- 渲染结果返回用户,循环继续
关键约束:Model 不知道 View 的存在。业务逻辑不依赖任何展示技术,才能做到同一 Model 支撑 Web/APP/报表多种 View,也才能单测业务而不启动 Web 容器。
Spring MVC 的落地映射
Spring MVC 把三角关系落到一组协作组件上:
- DispatcherServlet:前端控制器,所有请求入口,负责分发
- HandlerMapping:URL → Controller 方法的映射(@RequestMapping 解析结果)
- Controller(@Controller/@RestController):接收参数、调用 Service(Model 层业务)、返回模型或 JSON
- ViewResolver + View:把模型数据渲染为 HTML(Thymeleaf/JSP);REST 场景下由 HttpMessageConverter 直接写 JSON,View 退化为消息体
- Model/ModelAndView:Controller 与 View 之间的数据载体
一次 GET /user/1 的旅程:DispatcherServlet → HandlerMapping 定位 UserController#get → 参数解析器绑定路径变量 → Service 查库(Model)→ 返回值经转换器序列化为 JSON 写回。MVC 思想在框架里变成了可替换组件的流水线。
分层边界与常见误用
- Controller 不写业务:只做参数校验、调用编排、结果封装;业务在 Service(Model 层),否则换接口形态(Web→RPC)时要重写控制器
- Model 不依赖 Web 类型:Service 方法签名里出现 HttpServletRequest 就是分层被穿透的信号
- View 不拼业务逻辑:模板里写 if-else 计算金额,等于把 Model 的职责 leak 到展示层
- 贫血 vs 充血:MVC 不规定 Model 内部形态;DDD 倾向充血模型(行为进领域对象),传统三层常用贫血模型(实体+Service),团队内统一即可
MVC 的变体谱系
- MVP:Presenter 持有 View 接口,View 被动化,利于 UI 单测(Android 早期常用)
- MVVM:ViewModel + 双向绑定(Vue/React 状态管理思想同源),View 观察状态自动更新
- 前后端分离:后端 MVC 的 V 退化为 JSON 契约,前端自成 MVVM 体系——MVC 在服务端简化为 MC + API 契约
变体在变”View 如何感知 Model 变化”,不变的是展示、业务、调度三者分离的内核。
为什么值得坚持
MVC 的收益不在”好看的分层图”,而在变化隔离带来的三个工程能力:界面改版不动业务、业务重构不动界面、调度逻辑(路由/鉴权/异常处理)集中可插拔(拦截器/AOP)。任何让这三者重新耦合的写法(Controller 写 SQL、模板算业务),都在透支这套思想的红利。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 非鱼小站!
评论
WalineDisqus











