Spring Boot 全局异常处理 + 参数校验进阶:让接口告别 “500 报错” 和 “脏数据”
如果用户输入 “图书价格 =-100 元”“作者名空着提交”,或者系统突然抛个空指针异常,接口直接返回 “500 Internal Server Error”—— 用户看懵了,前端没法处理,后端排查还费劲,这就是 “接口不健壮” 的典型问题。
Spring Boot 早就帮咱们备好了解决方案:参数校验(Validation)+ 全局异常处理(@RestControllerAdvice) ,就像奶茶店的 “点单校验 + 异常应对流程”:点单时自动校验 “杯数不能为负、甜度不能选‘超甜 + 无糖’”(参数校验),制作时原料不足直接提示 “今日珍珠售罄”(友好异常提示),而不是让顾客等半天后说 “做不了”。
今天全程聚焦 Spring Boot 生态,以图书管理系统为案例,手把手实现 “参数自动校验 + 全局异常统一处理”,让接口既能防住脏数据,又能在出错时返回清晰提示,彻底告别杂乱的 500 报错,新手也能直接复制代码落地!
一、先搞懂:为什么需要这两个功能?(奶茶店类比)
1. 接口参数校验:防 “脏数据” 进门
没有参数校验的接口,就像奶茶店不校验点单信息:顾客可以点 “-2 杯奶茶”“甜度选‘无糖 + 全糖’”,这些非法请求会直接打到数据库,要么插入垃圾数据,要么触发业务异常。
Spring Boot 的spring-boot-starter-validation依赖,能通过注解自动校验参数(如必填、长度、格式),不用手动写if (bookName == null) { throw 异常 },代码更简洁。
2. 全局异常处理:统一 “出错提示”
没有全局异常处理时,系统报错会返回默认的 500 页面或杂乱的堆栈信息:
- 用户看到 “Whitelabel Error Page”,完全不知道啥问题;
- 前端拿到一堆堆栈日志,没法解析错误原因;
- 后端排查需要翻日志找具体异常,效率低。
全局异常处理就像奶茶店的 “统一异常应对话术”:不管是原料不足、点单非法,还是机器故障,都统一提示 “清晰的错误信息 + 错误码”,比如 “[1001] 图书价格不能小于 0 元”“[5000] 系统繁忙,请稍后重试”。
核心价值(企业刚需)
- 减少重复代码:参数校验不用写一堆 if-else,异常处理不用在每个接口 try-catch;
- 提升用户体验:出错时返回明确提示,而不是模糊的 500 报错;
- 降低排查成本:统一异常日志格式,快速定位问题;
- 保证数据安全:拦截非法参数,避免脏数据进入系统。
二、实操 1:接口参数校验 ——Spring Boot 自带 Validation
Spring Boot 2.3 + 后,validation从 web 依赖中拆分出来,需要单独引入依赖,通过注解就能实现参数校验,全程零手动判断。
步骤 1:加依赖(Spring Boot 参数校验核心)
xml
<!-- Spring Boot参数校验依赖(生态内核心依赖) -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId><version>2.7.10</version>
</dependency><!-- web依赖(已存在,确保有) -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
步骤 2:给实体类加校验注解(定义 “点单规则”)
以Book实体类为例,给需要校验的字段加注解(如必填、价格大于 0、书名长度限制):
java
运行
package com.example.springbootdemo.entity;import lombok.Data;
import org.hibernate.validator.constraints.Length;import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.util.Date;@Data
public class Book {private Long id; // 主键自增,新增时不用传,无需校验// 图书名:必填,长度2-50字@NotBlank(message = "图书名不能为空") // 字符串非空且不是纯空格@Length(min = 2, max = 50, message = "图书名长度必须在2-50字之间")private String bookName;// 作者:必填,长度2-20字@NotBlank(message = "作者不能为空")@Length(min = 2, max = 20, message = "作者名长度必须在2-20字之间")private String author;// 价格:必填,大于0,最多2位小数@NotNull(message = "价格不能为空") // 非基本类型用@NotNull@DecimalMin(value = "0.01", message = "图书价格不能小于0.01元")@DecimalMax(value = "9999.99", message = "图书价格不能超过9999.99元")@Digits(integer = 4, fraction = 2, message = "图书价格最多4位整数、2位小数")private BigDecimal price;// 出版时间:必填,不能是未来时间@NotNull(message = "出版时间不能为空")@PastOrPresent(message = "出版时间不能是未来时间") // 只能是过去或当前时间private Date publishTime;private Integer isDeleted;
}
常用校验注解清单(直接套用)
| 注解 | 作用 | 适用场景 |
|---|---|---|
| @NotBlank(message="") | 字符串非空且不是纯空格 | 书名、作者等字符串必填字段 |
