🌟 前言
“为什么前端传的参数总是不合法?”
“如何避免写一堆if判断来校验参数?”
本文将手把手教你使用Spring Boot的校验框架,从基础注解→嵌套校验→自定义规则→全局异常处理,彻底告别参数校验的烦恼!
一、参数校验为什么重要?
1.1 血的教训
- 案例1:用户手机号传了
null
→ 短信接口报空指针 - 案例2:订单金额传入负数 → 财务对账出问题
- 案例3:邮箱格式错误 → 营销邮件发送失败
1.2 校验的核心目标
- 安全性:防止SQL注入、XSS攻击
- 健壮性:避免脏数据污染数据库
- 友好性:给前端明确的错误提示
二、Spring Boot参数校验的四种姿势
2.1 原始方式(不推荐)
public String createUser(String name, Integer age) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("姓名不能为空");
}
if (age == null || age < 1 || age > 150) {
throw new IllegalArgumentException("年龄不合法");
}
// 业务逻辑...
}
❌缺点:代码臃肿、重复劳动
2.2 注解校验(推荐✨)
步骤1:添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
步骤2:在DTO类上加注解
@Data
public class UserDTO {
@NotBlank(message = "姓名不能为空")
private String name;
@NotNull(message = "年龄必填")
@Min(value = 1, message = "年龄不能小于1岁")
@Max(value = 150, message = "年龄不能超过150岁")
private Integer age;
@Email(message = "邮箱格式错误")
private String email;
}
步骤3:在Controller中添加@Valid
@PostMapping("/users")
public Result<?> createUser(@RequestBody @Valid UserDTO userDTO) {
// 业务逻辑...
}
三、常用校验注解大全
注解 | 作用 | 示例 |
---|---|---|
@NotNull | 值不能为null | 校验对象类型字段 |
@NotBlank | 字符串不能为空 | 用户名、地址等 |
@Min /@Max | 数值范围限制 | 年龄、金额 |
@Pattern | 正则表达式校验 | 手机号、身份证号 |
@Email | 邮箱格式校验 | 用户注册邮箱 |
@Size | 集合或字符串长度限制 | 密码长度、列表大小 |
@Future /@Past | 日期校验 | 生日、活动时间 |
四、嵌套校验与分组校验
4.1 嵌套对象校验
@Data
public class OrderDTO {
@Valid // 必须加此注解
private UserDTO user;
@NotEmpty
private List<@Valid ProductDTO> products;
}
@Data
public class ProductDTO {
@NotBlank
private String name;
}
4.2 分组校验(按场景区分规则)
// 定义分组接口
public interface CreateGroup {}
public interface UpdateGroup {}
// DTO中使用分组
@Data
public class UserDTO {
@Null(groups = CreateGroup.class)
@NotNull(groups = UpdateGroup.class)
private Long id;
}
// Controller指定分组
@PostMapping("/users")
public Result<?> createUser(@Validated(CreateGroup.class) @RequestBody UserDTO dto) {
//...
}
五、自定义校验规则
5.1 实现手机号校验器
步骤1:定义注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneValidator.class)
public @interface Phone {
String message() default "手机号格式错误";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
步骤2:编写校验逻辑
public class PhoneValidator implements ConstraintValidator<Phone, String> {
private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) return true; // 允许为空,配合@NotBlank使用
return PHONE_PATTERN.matcher(value).matches();
}
}
步骤3:在DTO中使用
@Phone
private String mobile;
六、全局异常处理(统一返回格式)
@RestControllerAdvice
public class GlobalExceptionHandler {
// 捕获参数校验异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<?> handleValidException(MethodArgumentNotValidException e) {
List<String> errors = e.getBindingResult().getFieldErrors().stream()
.map(item -> item.getField() + ": " + item.getDefaultMessage())
.collect(Collectors.toList());
return Result.error(400, "参数错误", errors);
}
}
响应示例:
{
"code": 400,
"message": "参数错误",
"data": [
"mobile: 手机号格式错误",
"age: 年龄不能小于1岁"
]
}
七、常见坑点与解决方案
7.1 校验不生效?
- 检查1:Controller方法是否添加
@Valid
或@Validated
- 检查2:DTO字段是否使用正确的注解(如String用
@NotBlank
而非@NotNull
) - 检查3:是否遗漏
spring-boot-starter-validation
依赖
7.2 国际化消息
在resources
下创建ValidationMessages.properties
:
user.name.notblank=用户名不能为空
user.age.min=年龄不能小于{value}岁
在注解中引用:
@NotBlank(message = "{user.name.notblank}")
private String name;
📚 实战总结
Spring Boot参数校验体系
├─ 基础校验:内置注解+@Valid
├─ 高级技巧
│ ├─ 嵌套校验
│ ├─ 分组校验
│ └─ 自定义校验
└─ 异常处理
├─ 全局异常捕获
└─ 统一响应格式
#SpringBoot教程 #参数校验 #API开发 #小白必备 #优快云博文
你在参数校验中踩过哪些坑?
评论区分享你的经历,点赞最高的送《Spring Boot实战派》电子书!🚀
相关推荐:
(转载需授权,侵权必究)
好的,关于这个问题我们今天就先分享到这里,希望能帮助到屏幕前为代码发愁的您。如果觉得有帮助,希望能在Taobao搜索“鹿溪IT工作室”买一个Android小项目来练手,友友们给个好评,支持一下创作者不易!