几乎所有后端项目初期都会出现一个通病:参数校验随心所欲。
开发为了快速迭代,所有参数判断全部手写if/else,有的接口校验、有的不校验、有的校验规则不一致。上线后频繁出现:空指针异常、负数金额入库、手机号格式错误、超出范围参数导致业务报错、非法脏数据落库。
零散的手写校验代码,不仅臃肿难维护,还极易出现校验遗漏。本文梳理参数校验所有高频坑点,给出可直接上线的统一注解校验规范 + 全局异常捕获 + 分组校验实战,适配所有SpringBoot项目。
一、参数校验最常见5大致命坑点
1. 全量手写if判断,代码极度冗余
每个接口单独写null判断、空串判断、长度判断、范围判断,重复代码满天飞,项目臃肿难维护,新增接口需要重复写大量校验逻辑。
2. 校验规则不统一,同字段不同规则
用户手机号、订单金额、账号状态等通用字段,不同接口校验规则不一致,有的宽松、有的严格,导致系统数据标准混乱,对账异常。
3. 只校验非空,不校验参数范围与格式
很多接口仅判断参数不为空,忽略数值正负、长度上限、正则格式。出现负数金额、超长备注、非法手机号、异常状态码,引发业务逻辑错乱。
4. 嵌套对象、集合参数完全不校验
单层参数偶尔校验,List集合、嵌套DTO内部字段完全裸奔,批量提交场景下,子参数非法无拦截,批量数据脏入库。
5. 校验异常无统一处理,返回格式混乱
参数错误直接抛出原生异常,前端返回信息杂乱、报错不友好,无法精准提示用户输入错误位置,前后端联调效率极低。
二、传统手写校验 VS 注解统一校验(优劣对比)
传统错误写法(冗余且极易漏判)
// 臃肿、重复、难维护
public Result createOrder(OrderDTO dto){
if(dto == null){
return Result.fail("参数不能为空");
}
if(dto.getAmount() == null || dto.getAmount() <= 0){
return Result.fail("订单金额必须大于0");
}
if(dto.getPhone() == null || "".equals(dto.getPhone())){
return Result.fail("手机号不能为空");
}
if(dto.getPhone().length() != 11){
return Result.fail("手机号格式错误");
}
// 大量重复判断...
}企业级正确写法(注解零代码校验)
public Result createOrder(@Valid @RequestBody OrderDTO dto){
// 无需任何手写校验代码,全部注解自动校验
return orderService.create(dto);
}三、生产级DTO注解校验规范
基于 Hibernate Validator 实现,覆盖空值、长度、数值、正则、嵌套、集合全场景
@Data
public class OrderDTO {
// 非空+数值范围校验
@NotNull(message = "订单金额不能为空")
@DecimalMin(value = "0.01", message = "订单金额必须大于0")
private BigDecimal amount;
// 手机号正则校验
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
// 长度限制
@Size(max = 200, message = "备注内容不能超过200字")
private String remark;
// 嵌套对象递归校验
@Valid
@NotNull(message = "收货信息不能为空")
private AddressDTO address;
// 集合批量递归校验
@Valid
@NotEmpty(message = "订单商品列表不能为空")
private List<OrderItemDTO> itemList;
}四、分组校验实战(新增/修改不同校验规则)
业务高频场景:新增无需ID、修改必须传ID,通过分组校验完美解决,无需拆分DTO
// 分组标识
public interface AddGroup {}
public interface UpdateGroup {}
@Data
public class UserDTO {
// 新增不校验,修改必填
@NotNull(message = "用户ID不能为空", groups = UpdateGroup.class)
private Long userId;
// 新增修改都必填
@NotBlank(message = "用户名不能为空", groups = {AddGroup.class, UpdateGroup.class})
private String username;
}
// 接口使用
@PostMapping("/add")
public Result add(@Validated(AddGroup.class) @RequestBody UserDTO dto){}
@PostMapping("/update")
public Result update(@Validated(UpdateGroup.class) @RequestBody UserDTO dto){}五、全局异常统一处理(规范前端返回)
统一拦截参数校验异常,返回标准化JSON,前端无需适配多种报错格式
@RestControllerAdvice
public class GlobalExceptionHandler {
// 拦截参数校验异常
@ExceptionHandler(MethodArgumentValidException.class)
public Result validException(MethodArgumentValidException e){
String message = e.getBindingResult().getFieldError().getDefaultMessage();
return Result.fail(message);
}
}六、参数校验落地规范

所有接口入参统一使用注解校验,禁止手写if/else基础判断
基础字段统一校验规则:手机号、身份证、金额、账号全局统一正则与范围
嵌套对象、集合必须加@Valid,防止批量参数校验遗漏
区分分组校验,新增、修改、查询场景差异化校验
禁止参数裸奔入库,所有前端传入参数必须经过校验拦截
统一异常返回格式,杜绝原生异常直接返回前端
七、落地检查清单

项目是否去除大量冗余手写参数判断?
非空、数值、长度、正则是否全部使用注解校验?
嵌套对象、集合参数是否开启递归校验?
新增/修改差异化场景是否使用分组校验?
是否配置全局异常拦截,统一报错返回?
通用字段是否全局统一校验标准?
八、总结
参数校验看似是基础小事,却是提升项目整洁度、减少线上BUG、规范数据标准的核心关键。
抛弃杂乱的手写if判断,统一使用注解校验+全局异常处理,不仅能大幅精简代码、降低维护成本,还能从源头拦截非法参数、杜绝脏数据,彻底解决因入参不规范导致的空指针、业务错乱、数据异常等顽固问题。
在线
电话
微信
需求
TOP