Java 后端手册JAVA BACKEND

CHAPTER 05应用层 · WEB

REST 接口

Controller、Spring MVC、参数校验、统一异常处理与 OpenAPI。把业务安全地暴露成 HTTP 接口。

开始阅读难度中级先修第三、四章约2.5小时
05.1

REST 与 HTTP

REST 用资源 URL + HTTP 方法表达操作:GET 查、POST 建、PUT 全量改、PATCH 部分改、DELETE 删。状态码表达结果。

方法语义成功码
GET查询200
POST创建201
PUT/PATCH修改200
DELETE删除204
05.2

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);
    }
}
05.3

请求与响应体

用 @RequestBody 接收 JSON 体,@RequestParam 取查询参数,@PathVariable 取路径变量。返回对象由消息转换器序列化为 JSON。

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public OrderDTO create(@RequestBody @Valid CreateOrderCmd cmd) {
    return service.create(cmd);
}
DTO 而非实体

接口层用 DTO(数据传输对象),不要把 JPA 实体直接序列化出去,避免暴露内部字段与懒加载异常。

05.4

参数校验

Jakarta Validation(@NotNull/@Size/@Pattern)在入口守卫数据,@Valid 触发校验,失败抛 MethodArgumentNotValidException。

public record CreateOrderCmd(
    @NotNull Long sku,
    @Positive int qty,
    @Email String contact
) {}
05.5

统一异常处理

用 @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 留给日志,防止信息泄露。

05.6

分页与排序

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,desc
05.7

OpenAPI 文档

引入 springdoc-openapi,自动根据注解生成交互式 Swagger UI,前端联调与文档同步,避免文档腐化。

@Operation(summary = "创建订单")
@ApiResponse(responseCode = "201", description = "创建成功")
public OrderDTO create(@RequestBody @Valid CreateOrderCmd cmd) { ... }
// 访问 /swagger-ui.html
05.8

常见陷阱与 FAQ

返回实体会出什么问题?

实体可能含懒加载关联,序列化时触发 LazyInitializationException;还会把内部字段(如密码哈希)泄露给前端。用 DTO 投影。

校验不生效?

忘加 @Valid 注解会让校验被跳过。确保方法参数前有 @Valid,且依赖包含 validation 起步包。

路径变量和 JSON 同名字段冲突?

互不干扰:@PathVariable 取 URL 段,@RequestBody 取体。命名重叠也不冲突,但保持语义清晰更好。

05.9

实战练习与资源

延伸资源