本节摘要:用注解写出一套完整的 RESTful 接口。本节以"用户管理"为例,实现增删改查(CRUD)四类接口、处理请求参数、返回 JSON 数据,并给出一个完整接口示例。
阅读完本节,你应当能够:
"接口怎么写?"——把 RESTful 的"资源 + 方法"翻译成注解即可:资源是 /users,方法是 @GetMapping/@PostMapping……四行注解,一套 CRUD 就有了。
CRUD 接口是固定套路:
| 操作 | 方法 | URL |
|---|---|---|
| 查列表 | GET | /users |
| 查单个 | GET | /users/{id} |
| 新增 | POST | /users |
| 修改 | PUT | /users/{id} |
| 删除 | DELETE | /users/{id} |
@RestController @RequestMapping("/users") public class UserController { @GetMapping public List<User> list() { ... } // 查列表 @GetMapping("/{id}") public User get(@PathVariable Long id) { ... } // 查单个 @PostMapping public User create(@RequestBody User user) { ... } // 新增 @DeleteMapping("/{id}") public void delete(@PathVariable Long id) { ... } // 删除 }
| 参数类型 | 注解 | 场景 |
|---|---|---|
| 路径参数 | @PathVariable | /users/1 |
| 查询参数 | @RequestParam | ?page=1 |
| 请求体 | @RequestBody | JSON 数据 |
💡 关键直觉:先定"资源",再套"方法"——想清楚有哪些资源(users/orders),每个资源的 CRUD 就是一套模板化接口。写接口前先画资源清单。
@GetMapping("/{id}") public User get(@PathVariable Long id) { return service.findById(id) .orElseThrow(() -> new NotFoundException("用户不存在")); } // 返回 404 + 错误信息
⚠️ 常见坑:错误也返回 200。接口出错必须返回对应状态码(400/404/500),前端才能正确判断——统一 200 会把错误藏起来。
用 Postman/API 工具测全部方法 GET 浏览器可测 POST/PUT/DELETE 用工具测
接口会写了,下一节接数据库——数据访问。
Q1:为什么 CRUD 接口是"模板化"的?
因为针对同一个资源,操作就那么几种:查列表、查单个、新增、修改、删除。每种操作的 HTTP 方法、URL 模式、参数类型都是固定的套路。所以写接口时,你先想清楚资源清单(users、orders、products),然后每个资源套一遍 CRUD 模板即可。框架还提供了对应的注解(GetMapping/PostMapping/PutMapping/DeleteMapping),让这个模板几乎不需要额外配置。
Q2:路径参数、查询参数、请求体参数什么时候用?
路径参数用于"定位单个资源":/users/1 中的 1 表示要操作 id 为 1 的用户,用 @PathVariable 取。查询参数用于"筛选或分页":/users?page=2&size=10 中的 page、size,用 @RequestParam 取。请求体用于"提交数据":POST 新增用户时把用户数据放在请求体的 JSON 里,用 @RequestBody 接收。选错参数类型不会报错,但接口设计就不规范,别人用起来也困惑。
Q3:接口参数校验应该在哪做?
框架层可以做基础校验(必填、类型、长度),业务层做规则校验(比如金额不能为负、状态合法)。两层配合:接口层校验"数据形状对不对",业务层校验"业务上允不允许"。即使接口层校验了,业务层也要再校验一次,因为接口层可能被绕过。校验失败要返回 400 状态码和清晰的错误信息,别返回 500。
Q4:接口出错了,为什么不能统一返回 200?
因为前端依赖状态码判断结果。统一 200 意味着"不管成没成功都提示成功",错误就被隐藏了——用户以为下单成功,实际订单没创建。正确做法是:成功返回 2xx,参数错误返回 400,没找到返回 404,服务器异常返回 500,响应体里再带一个业务错误码和错误信息。这样前端能区分"是用户的问题、是资源缺失、还是系统故障",排查效率天差地别。
动手建议:把本节的用户 CRUD 完整实现一遍,然后用接口测试工具(Postman 或浏览器开发者工具)分别测:GET 查列表、GET 查单个、POST 新增、DELETE 删除。重点观察两点:一是每次请求返回的状态码是否符合语义(创建成功应该是 201);二是请求一个不存在的用户时,是否返回了 404 而不是 200。接口写完,再画一张"资源—方法—URL"对照表,确认自己的设计符合 RESTful 约定。
本节最重要的练习,是把用户管理接口的五件套完整实现并测试。步骤如下:
第一步,写查列表接口。用 GET 方法返回所有用户,响应是用户对象的 JSON 数组。验收标准:用接口工具访问,能返回数据且状态码是 200。
第二步,写查单个接口。用 GET 方法加路径参数,路径形如 /users/1。访问存在的 id 返回对应数据,访问不存在的 id 返回 404。验收标准:两种结果都能正确区分状态码。
第三步,写新增接口。用 POST 方法接收请求体(JSON 格式的用户数据),创建成功后返回 201 状态码和创建的数据。验收标准:发送一段合法 JSON,能在响应里看到创建结果。
第四步,写修改接口。用 PUT 方法加路径参数,接收请求体,更新指定用户。验收标准:修改后再次查询,数据已变化。
第五步,写删除接口。用 DELETE 方法加路径参数,删除指定用户。验收标准:删除后再查询该用户,返回 404。
第六步,把五件套连起来做"链路测试":新增一个用户、查列表确认存在、改它的资料、再删除、再查确认不存在。整套走完不报错,你的 CRUD 就过关了。
做完这套练习,你写的每个接口都有明确验收标准,状态码和数据结构也符合约定。这正是生产环境接口开发的标准节奏——写一个、测一个、验收一个。
CRUD 接口是模板化工作,练习它的最好方式就是"五件套全写、全测"。状态码对、数据对、增删改查链路通,你就真正掌握了 Spring Boot 接口开发的日常。