生产级 Spring Boot API — 第2部分:清晰代码结构、控制器与 DTO

发布: (2026年1月18日 GMT+8 03:52)
3 min read
原文: Dev.to

Source: Dev.to

本文涵盖内容

  • 控制器职责(API 边界,而非业务逻辑)
  • 为什么 @RestController 不止是“返回 JSON”
  • 构造函数注入(以及它为何是强制性的)
  • Spring 的 stereotype 注解以及语义为何重要
  • 实体 vs DTO(以及为何暴露实体是危险的)
  • 在生产系统中使用 Lombok
  • 为什么 ModelMapper 能保持层次清晰

控制器层(API 边界)

@RestController
@RequestMapping("/orders")
public class OrderController {

    private final OrderService orderService;

    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }
}

@RestController 的真实含义

  • 将类注册为 HTTP 请求处理器
  • 返回 JSON(而非视图)
  • DispatcherServlet 集成

该类定义 API 合约,而不是业务逻辑。

构造函数注入(生产环境不可或缺)

public OrderController(OrderService orderService) {
    this.orderService = orderService;
}

为何使用构造函数注入:

  • 依赖显式化
  • 对象不可变
  • 易于测试
  • 启动时快速失败(如果缺少依赖,应用不应启动)

Stereotype 注解(语义很重要)

注解用途
@Service业务逻辑
@Repository数据访问
@ControllerMVC 层
@RestControllerREST API

它们都继承自 @Component,但会添加意义、可读性以及层级特定的行为。

实体 vs DTO(绝不暴露实体)

实体

  • 映射到数据库表
  • 仅用于持久化

DTO

  • 用于 API 通信
  • 保护内部结构

实体随数据库需求变化;DTO 随 API 需求变化。

Lombok(生产环境的福音)

没有 Lombok 时:

  • 缺少 setter → JSON 字段为 null
  • 缺少 getter → 响应为空
  • 大量样板代码

使用 Lombok:

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Order {
    private Long id;
    private String description;
    // other fields...
}
  • 自动生成 getter / setter、构造函数、builder 等
  • 让实体保持简洁

在大型 Spring Boot 代码库中,Lombok 几乎是必需的。

ModelMapper(保持层次分离)

  • 在实体 ⇄ DTO 之间转换
  • 让控制器保持简洁
  • 防止泄露持久化模型

持久化指数据在应用运行时之外仍然存在(如存入数据库)。


这是一系列 3 篇文章中的第 2 篇,主题为 Production‑Grade Spring Boot API Design

👉 第 3 篇 讨论一致的 API 响应、BaseResponseResponseEntity 以及全局异常处理。

Back to Blog

相关文章

阅读更多 »

让我们分离分离

简介 在2025年最后几天,我们的团队负责人额外请了一天假,错过了一个重要会议。最近的重组后,一位同事离职……