Spring MVC 中的 Controller 是什么?如何定义一个 Controller?
- 标签:后端、Spring
🏛 业务架构师
Controller 是 Spring MVC 里HTTP 请求与业务逻辑之间的适配层:接收请求、校验参数、调用 Service、组装响应。定义方式:
java
@RestController
@RequestMapping("/api/orders")
public class OrderController {
private final OrderService orderService; // 构造器注入
@GetMapping("/{orderId}")
public Result<OrderVO> detail(@PathVariable Long orderId) {
return Result.ok(orderService.getDetail(orderId));
}
@PostMapping
public Result<Long> create(@Validated @RequestBody OrderCreateDTO dto) {
return Result.ok(orderService.create(dto));
}
}@RestController = @Controller + @ResponseBody,直接返回 JSON。
架构师视角,Controller 的**"薄"是团队代码质量的第一体检指标**:
- 只做四件事:参数校验、权限上下文读取、调用 Service、结果组装。出现 if/else 业务判断、直接操作数据库,就是越界——业务规则必须沉淀在 Service,否则同样的规则没法被定时任务、MQ 消费者复用;
- DTO 与领域模型分离:入参/出参用 DTO 隔离,防止内部表结构通过接口泄漏,字段变更不破坏契约;
- 统一返回结构与错误码:Controller 不写 try-catch 兜底,异常交给全局处理——保证所有接口对外行为一致。
一句话:Controller 是系统的"门面",门面的纪律性决定了整个代码库的演进秩序。
🏗 系统架构师
定义:@Controller(页面)或 @RestController(REST,等价 Controller 加 ResponseBody)标注类,@RequestMapping 及其组合注解声明路由,方法即 Handler。
java
@RestController
@RequestMapping("/orders")
public class OrderController {
@PostMapping
public Result<OrderVO> create(@Valid @RequestBody CreateOrderDTO dto) {...}
}架构定位:Controller 是协议适配层,不是业务层。我评审 Controller 只看三条:
- 薄:参数校验 → 调一个应用服务 → 组装 VO,没有 if 业务分支;
- 无状态:不存成员变量,天然支持水平扩展;
- 契约先行:入参 DTO 与出参 VO 和领域模型隔离——API 演进(加字段、版本化)不反向侵入领域层;出参不直接吐实体,防止内部表结构变化变成破坏性 API 变更。
Controller 写厚是分层失守的第一张多米诺骨牌:业务逻辑混进去后无法复用、无法测试,改 API 就得改业务。
💻 全栈开发专家
Controller 是 MVC 里的 C——接请求、参数校验、调 Service、组装响应,不写业务逻辑(薄 Controller 原则):
java
@RestController // = @Controller + @ResponseBody
@RequestMapping("/api/v1/orders")
@Validated
public class OrderController {
private final OrderService orderService;
public OrderController(OrderService orderService) { this.orderService = orderService; }
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Result<OrderVO> create(@RequestBody @Valid OrderCreateReq req) {
return Result.ok(orderService.create(req));
}
@GetMapping("/{id}")
public Result<OrderVO> detail(@PathVariable Long id) {
return Result.ok(orderService.get(id));
}
}要点:@Controller 返回视图名(模板渲染),@RestController 直接序列化 JSON,前后端分离无脑后者;类上 @RequestMapping 收敛路径前缀。
我的 code review 三条规约:Controller 只做协议层转换(DTO 与 VO 之间),复杂逻辑下沉 Service;DTO 与实体分离,避免实体直接出网(字段泄露和序列化事故);一个 Controller 对应一个资源,URL 用复数名词。看到 500 行的 Controller,基本就是职责漏了,面试拿这条说事很加分。