REST 与 HTTP
REST 用资源 URL + HTTP 方法表达操作:GET 查、POST 建、PUT 全量改、PATCH 部分改、DELETE 删。状态码表达结果。
| 方法 | 语义 | 成功码 |
|---|---|---|
| GET | 查询 | 200 |
| POST | 创建 | 201 |
| PUT/PATCH | 修改 | 200 |
| DELETE | 删除 | 204 |
Controller 基础
@RestController 组合了 @Controller 与 @ResponseBody。用 @GetMapping 等映射路由,路径含 {id} 占位。
@RestController
@RequestMapping("/api/orders")
public class OrderController {
private final OrderService service;
public OrderController(OrderService service) { this.service = service; }
@GetMapping("/{id}")
public OrderDTO get(@PathVariable Long id) {
return service.findById(id);
}
}请求与响应体
用 @RequestBody 接收 JSON 体,@RequestParam 取查询参数,@PathVariable 取路径变量。返回对象由消息转换器序列化为 JSON。
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public OrderDTO create(@RequestBody @Valid CreateOrderCmd cmd) {
return service.create(cmd);
}接口层用 DTO(数据传输对象),不要把 JPA 实体直接序列化出去,避免暴露内部字段与懒加载异常。
参数校验
Jakarta Validation(@NotNull/@Size/@Pattern)在入口守卫数据,@Valid 触发校验,失败抛 MethodArgumentNotValidException。
public record CreateOrderCmd(
@NotNull Long sku,
@Positive int qty,
@Email String contact
) {}统一异常处理
用 @RestControllerAdvice + @ExceptionHandler 集中把异常转成统一错误响应,避免各处散落 try/catch。
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(OrderNotFoundException.class)
public ResponseEntity<ErrorBody> handle(OrderNotFoundException e) {
return ResponseEntity.status(404)
.body(new ErrorBody("ORDER_NOT_FOUND", e.getMessage()));
}
}对外错误体只返回业务码与可读信息,技术堆栈与 SQL 留给日志,防止信息泄露。
分页与排序
Spring Data 提供 Pageable,把 page/size/sort 参数自动转成分页查询,避免手写 limit/offset。
@GetMapping
public Page<OrderDTO> list(@RequestParam Pageable pageable) {
return service.list(pageable);
}
// GET /api/orders?page=0&size=20&sort=createdAt,descOpenAPI 文档
引入 springdoc-openapi,自动根据注解生成交互式 Swagger UI,前端联调与文档同步,避免文档腐化。
@Operation(summary = "创建订单")
@ApiResponse(responseCode = "201", description = "创建成功")
public OrderDTO create(@RequestBody @Valid CreateOrderCmd cmd) { ... }
// 访问 /swagger-ui.html常见陷阱与 FAQ
实体可能含懒加载关联,序列化时触发 LazyInitializationException;还会把内部字段(如密码哈希)泄露给前端。用 DTO 投影。
忘加 @Valid 注解会让校验被跳过。确保方法参数前有 @Valid,且依赖包含 validation 起步包。
互不干扰:@PathVariable 取 URL 段,@RequestBody 取体。命名重叠也不冲突,但保持语义清晰更好。