LESSON 5.6 / BACKEND & API

把后端概念迁移到 Java / Spring Boot

语言和框架会改变写法,不会改变请求、路由、校验、业务逻辑和响应这些核心角色。

预计阅读15–20 分钟
完成结果能把后端知识从示例语言迁移到 Java 技术栈。
本课目标
  • 能把后端知识从示例语言迁移到 Java 技术栈。
  • Controller、Service、Repository 的职责
  • 用 Spring Boot 重写 health 和文本处理接口,保持契约不变。
开始之前
  • 完成 5.5「完成第一次前后端联调」
01

FOUNDATION

必须理解

语言和框架会改变写法,不会改变请求、路由、校验、业务逻辑和响应这些核心角色。

框架会变化,但路由、校验、业务逻辑和数据访问的职责可以迁移。把 Next.js 接口映射到 Java/Spring Boot,能理解企业后端常见分层,而不是重新从零背语法。

先建立整体直觉

同一份业务流程可以由不同语言的团队执行:窗口名称和制服不同,但受理、校验、处理、存档与回执仍是同一条链。

贯穿本课的实际场景

Next.js 的 route.ts 对应 Spring 的 Controller;独立业务函数对应 Service;Prisma 数据访问对应 Repository/JPA;响应 DTO 固定对外字段。

概念 1

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。

这一小节记住:按协议、业务和数据职责分层,而不是按模板堆文件。

概念 2

依赖注入、配置与环境变量

先用白话理解

Controller 先接住 HTTP 请求,Service 处理业务规则,Repository 负责访问数据。分层不是为了多建文件,而是避免改数据库时连接口代码也一起乱掉。

基础概念

依赖注入是由框架把对象需要的协作者交给它,而不是对象内部自行创建;配置与环境变量则为不同运行环境提供地址、凭证和开关。

进一步理解

构造器注入让 Service 明确依赖哪个 Repository,也便于测试时替换实现。Spring 容器负责创建和连接这些对象。

配置代码可以进入版本库,真实秘密通过环境提供。开发、测试和生产使用不同数据源,但字段和校验方式保持一致。

放进实际场景

TaskService 构造器接收 TaskRepository;测试传入内存替身,生产由 Spring 注入连接 PostgreSQL 的实现。

容易混淆的地方

依赖注入不是自动下载依赖,和 Maven 的包依赖管理不同;前者连接运行时对象,后者取得代码库。

这一小节记住:把协作者显式声明并交由外部组装,代码更容易替换和测试。

概念 3

DTO、校验、异常处理与统一响应

先用白话理解

DTO 用来规定接口接收和返回哪些字段,实体模型则更接近数据库。直接把实体整份返回,可能把不该公开的字段也一起送出去。

基础概念

DTO(Data Transfer Object,数据传输对象)规定接口接收或返回的数据形状;校验约束检查输入;异常处理把内部失败映射成统一安全响应。

进一步理解

请求 DTO 只包含调用方允许提交的字段,响应 DTO 只公开需要返回的字段。实体更接近数据库结构,不应直接承担外部契约。

`@Valid` 触发声明式校验,全局异常处理器统一转换常见失败,但业务异常仍需稳定分类,不能全部吞成 500。

放进实际场景

CreateTaskRequest 只接收 title,TaskResponse 返回 id、title、done;ownerId 从会话取得,实体中的内部审计字段不会对外。

容易混淆的地方

统一响应不等于所有结果都包进 200。HTTP 状态码仍应表达协议语义,统一的是错误结构与映射规则。

这一小节记住:DTO 隔离外部契约与内部实体,异常映射保持失败可理解。

Spring Controller 只负责协议入口
运行前先确认
  • 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);
}
这段代码在做什么

Controller 接收 HTTP 与校验结果,业务创建逻辑交给 Service,接口仍返回 201。

  1. @PostMapping 把 POST /api/tasks 交给当前方法。
  2. @Valid 在进入业务逻辑前校验请求 DTO,@RequestBody 读取 JSON。
  3. Controller 调用 Service 并用 ResponseEntity 返回 201,不在入口中直接写数据库。
你应该观察到

合法请求得到 201 与 TaskResponse;DTO 校验失败进入统一 400 错误处理;业务创建逻辑可在不启动 HTTP 的测试中单独验证。

02

AI COLLABORATION

AI 如何参与

让 AI 把已存在的小型 API 从一种技术栈映射到 Spring Boot,并逐层解释概念对应关系。

推荐协作顺序

  1. 1

    把已经跑通的 Next.js 接口契约给 AI,要求保持 JSON 不变。

  2. 2

    让它先做职责对应表,再写 Spring 的最小骨架。

  3. 3

    用同一组请求分别调用两套后端,比较状态码和正文。

可直接使用的 Prompt
请把 Next.js 的 POST /api/tasks 契约迁移为 Spring Boot。先列 Controller、Service、Repository、Request DTO、Response DTO 的职责与调用顺序,再给最小代码骨架。保持相同 JSON 与状态码,不引入登录和数据库细节。
应该得到什么

同一接口契约在不同框架下保持一致,代码边界清楚,不把全部逻辑放进 Controller。

人工检查清单

  • 确认 Bean Validation 在服务端生效,DTO 与实体分离,异常不会把堆栈直接返回用户。
  • 让 AI 把现有接口逐项映射到 Controller、Service、Repository 和 DTO,并解释每层存在理由。
  • 用相同请求与预期响应同时测试旧实现和 Spring 实现,确认迁移没有改变契约。
03

COMMON TRAPS

常见误区

错误不是需要隐藏的失败,而是帮助你看清系统边界的证据。下面三类问题在 AI 辅助学习中最常出现。

误区 1

把框架迁移理解成逐行翻译

你会看到
照着 TypeScript 语法换成 Java,完全没利用 Spring 的请求映射和校验。
为什么发生
照搬企业模板会让简单流程穿过许多无意义层,学习者只剩注解和文件名,反而看不到请求路径。
怎样纠正
迁移的是职责与契约,再用目标框架的惯用结构实现。
误区 2

所有逻辑都塞进 Controller

你会看到
接口类同时处理校验、业务和数据库,越来越难测试。
为什么发生
把业务规则写进 Controller 或 Repository 会绑定协议与存储,后续换入口或数据库时规则被复制。
怎样纠正
Controller 管 HTTP,Service 管规则,Repository 管数据访问。
误区 3

看见注解就全部复制

你会看到
类上堆满不理解的注解,删掉任何一个都不敢运行。
为什么发生
直接返回实体会把数据库字段变成公共接口,新增内部字段时可能无意泄露。
怎样纠正
每个注解都要能说出它注册了什么行为;暂时不用的不要加。
04

HANDS-ON

动手任务

用 Spring Boot 重写 health 和文本处理接口,保持契约不变。

准备条件
  • 完成 5.5「完成第一次前后端联调」

跟着做

  1. 01

    画出 Next.js Route Handler 的输入、处理和输出。

  2. 02

    将它映射到 Spring 五个常见角色。

  3. 03

    创建最小 Spring Boot Web 项目并运行健康页面。

  4. 04

    实现内存版 GET/POST Tasks Controller 与 Service。

  5. 05

    用相同五个接口测试对比 Next.js 和 Spring 响应。

完成标志

能把后端知识从示例语言迁移到 Java 技术栈。

加餐挑战

解释为什么团队可能选择 Spring Boot 后端,并列出它带来的额外学习与部署成本。

离开本课前,自问四件事

  • Controller、Service 与 Repository 的边界如何沿一次请求划分?
  • 依赖注入与包管理解决的是哪两类不同问题?
  • DTO 为什么不能简单等同于数据库实体?
  • 如何证明从其他技术栈迁移到 Spring 后接口契约保持不变?
完成本课了吗?

确认完成后,会同步更新学习中心的课程学习进度。