把后端概念迁移到 Java / Spring Boot
Spring Boot 是 Java 后端的一种成熟组织方式。选修本课的重点,是把已有 API 心智模型映射到控制器、服务和数据访问层。
- 能读懂一个最小任务接口的分层调用,并说明 Java 版本、构建工具和 Spring 依赖从哪里确定。
- Controller、Service、Repository 的职责
- 演练把后端概念迁移到 Java / Spring Boot后,应当能读懂一个最小任务接口的分层调用,并说明 Java 版本、构建工具和 Spring 依赖从哪里确定,并保留状态码、响应结构、进程输出和前后端同一次请求作为可重复检查的依据。
- 完成 5.5「完成第一次前后端联调」
FOUNDATION
必须理解
框架会变化,但路由、校验、业务逻辑和数据访问的职责可以迁移。把 Next.js 接口映射到 Java/Spring Boot,能理解企业后端常见分层,而不是重新从零背语法。
本课依次讲清Controller、Service、Repository 的职责、依赖注入、配置与环境变量和DTO、校验、异常处理与统一响应,最后通过“用相同五个接口测试对比 Next.js 和 Spring 响应”检查学习结果。
同一份业务流程可以由不同语言的团队执行:窗口名称和制服不同,但受理、校验、处理、存档与回执仍是同一条链。
Next.js 的 route.ts 对应 Spring 的 Controller;独立业务函数对应 Service;Prisma 数据访问对应 Repository/JPA;响应 DTO 固定对外字段。
Controller、Service、Repository 的职责
Java 会在编译时检查很多类型问题,编译后的字节码交给 JVM 运行。Spring Boot 再帮你把应用启动、Web 接口、配置和依赖组织起来。
基础概念
Controller 是 HTTP 入口,Service 承担业务规则,Repository 负责持久化访问。分层让协议、业务与存储变化保持相对独立。
进一步理解
Controller 读取路径、请求体和身份并返回状态;Service 判断任务能否创建或完成;Repository 用 JPA 或 SQL 查询数据库。调用方向通常由入口向内。
小应用可以保持层次轻量,但职责仍应清楚。建立文件不是目的,避免同一规则散落在 Controller 和 Repository 才是价值。
创建任务由 Controller 接收 DTO,Service 检查项目状态并生成业务结果,Repository 保存实体,Controller 转成 201 响应。
三层不是三台服务器,也不是每个方法都必须机械复制三遍;纯粹的简单读取可能只需很薄的 Service。
这一小节记住:按协议、业务和数据职责分层,而不是按模板堆文件。
依赖注入、配置与环境变量
Controller 先接住 HTTP 请求,Service 处理业务规则,Repository 负责访问数据。分层不是为了多建文件,而是避免改数据库时连接口代码也一起乱掉。
基础概念
依赖注入是由框架把对象需要的协作者交给它,而不是对象内部自行创建;配置与环境变量则为不同运行环境提供地址、凭证和开关。
进一步理解
构造器注入让 Service 明确依赖哪个 Repository,也便于测试时替换实现。Spring 容器负责创建和连接这些对象。
配置代码可以进入版本库,真实秘密通过环境提供。开发、测试和生产使用不同数据源,但字段和校验方式保持一致。
TaskService 构造器接收 TaskRepository;测试传入内存替身,生产由 Spring 注入连接 PostgreSQL 的实现。
依赖注入不是自动下载依赖,和 Maven 的包依赖管理不同;前者连接运行时对象,后者取得代码库。
这一小节记住:把协作者显式声明并交由外部组装,代码更容易替换和测试。
DTO、校验、异常处理与统一响应
DTO 用来规定接口接收和返回哪些字段,实体模型则更接近数据库。直接把实体整份返回,可能把不该公开的字段也一起送出去。
基础概念
DTO(Data Transfer Object,数据传输对象)规定接口接收或返回的数据形状;校验约束检查输入;异常处理把内部失败映射成统一安全响应。
进一步理解
请求 DTO 只包含调用方允许提交的字段,响应 DTO 只公开需要返回的字段。实体更接近数据库结构,不应直接承担外部契约。
`@Valid` 触发声明式校验,全局异常处理器统一转换常见失败,但业务异常仍需稳定分类,不能全部吞成 500。
CreateTaskRequest 只接收 title,TaskResponse 返回 id、title、done;ownerId 从会话取得,实体中的内部审计字段不会对外。
统一响应不等于所有结果都包进 200。HTTP 状态码仍应表达协议语义,统一的是错误结构与映射规则。
这一小节记住:DTO 隔离外部契约与内部实体,异常映射保持失败可理解。
- Spring Boot 项目已配置 Web 与校验依赖,并存在 taskService。
- CreateTaskRequest 与 TaskResponse 是明确的请求和响应 DTO。
@PostMapping("/api/tasks")
ResponseEntity<TaskResponse> create(@Valid @RequestBody CreateTaskRequest request) {
TaskResponse task = taskService.create(request.title());
return ResponseEntity.status(HttpStatus.CREATED).body(task);
}阅读把后端概念迁移到 Java / Spring Boot示例时,Controller 接收 HTTP 与校验结果,业务创建逻辑交给 Service,接口仍返回 201。
- @PostMapping 把 POST /api/tasks 交给当前方法。
- @Valid 在进入业务逻辑前校验请求 DTO,@RequestBody 读取 JSON。
- Controller 调用 Service 并用 ResponseEntity 返回 201,不在入口中直接写数据库。
合法请求得到 201 与 TaskResponse;DTO 校验失败进入统一 400 错误处理;业务创建逻辑可在不启动 HTTP 的测试中单独验证。
AI COLLABORATION
AI 如何参与
在把后端概念迁移到 Java / Spring Boot这一课,AI 负责根据真实材料解释Controller、Service、Repository 的职责并指出遗漏,学习者负责控制范围、执行修改和核对状态码、响应结构、进程输出和前后端同一次请求。
推荐协作顺序
- 1
把已经跑通的 Next.js 接口契约给 AI,要求保持 JSON 不变。
- 2
让它先做职责对应表,再写 Spring 的最小骨架。
- 3
用同一组请求分别调用两套后端,比较状态码和正文。
请只依据当前构建文件和依赖解释这个 Spring Boot 项目。先画请求从 Controller 到 Service 再到 Repository 的路径,再说明启动与测试方式。不要猜版本,不添加未声明依赖。
同一接口契约在不同框架下保持一致,代码边界清楚,不把全部逻辑放进 Controller;把后端概念迁移到 Java / Spring Boot的人工验收必须回到真实页面、请求、终端、测试或数据结果,不能用 AI 的文字说明代替。
人工检查清单
- 确认 Bean Validation 在服务端生效,DTO 与实体分离,异常不会把堆栈直接返回用户。
- 让 AI 把现有接口逐项映射到 Controller、Service、Repository 和 DTO,并解释每层存在理由。
- 用相同请求与预期响应同时测试旧实现和 Spring 实现,确认迁移没有改变契约。
COMMON TRAPS
常见误区
下面三类问题会让任务看似完成,却经不起刷新、错误输入或真实环境检查。先看现象,再找原因和修正方法。
照抄不同版本教程
- 你会看到
- 注解或配置与当前依赖不匹配
- 为什么发生
- 框架的配置和 API 会随版本变化,示例与当前依赖不一致就无法直接成立。
- 怎样纠正
- 先读取构建文件和官方对应文档
为了分层制造空代码
- 你会看到
- 每层只转发参数却增加跳转
- 为什么发生
- 只转发参数的层没有承担规则,却增加了阅读路径和修改位置。
- 怎样纠正
- 按真实职责决定边界
把秘密写入配置文件
- 你会看到
- 数据库凭证进入仓库
- 为什么发生
- 被 Git 跟踪的配置会进入历史和协作副本,秘密难以限制在运行环境。
- 怎样纠正
- 从环境注入并提交安全示例
HANDS-ON
动手任务
能读懂一个最小任务接口的分层调用,并说明 Java 版本、构建工具和 Spring 依赖从哪里确定。
- 完成 5.5「完成第一次前后端联调」
跟着做
- 01
画出 Next.js Route Handler 的输入、处理和输出。
- 02
将它映射到 Spring 五个常见角色。
- 03
创建最小 Spring Boot Web 项目并运行健康页面。
- 04
实现内存版 GET/POST Tasks Controller 与 Service。
- 05
用相同五个接口测试对比 Next.js 和 Spring 响应。
能读懂一个最小任务接口的分层调用,并说明 Java 版本、构建工具和 Spring 依赖从哪里确定。
解释为什么团队可能选择 Spring Boot 后端,并列出它带来的额外学习与部署成本。
离开本课前,自问四件事
- Controller、Service 与 Repository 的边界如何沿一次请求划分?
- 依赖注入与包管理解决的是哪两类不同问题?
- DTO 为什么不能简单等同于数据库实体?
- 如何证明从其他技术栈迁移到 Spring 后接口契约保持不变?
确认完成后,会同步更新学习中心的课程学习进度。