java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot接口参数校验

SpringBoot接口参数校验(Bean Validation)实战指南

作者:希望永不加班

在开发接口时,参数校验是必不可少的环节:前端传参是否为空、格式是否正确、数值是否合法,都需要后端严格校验,否则很容易出现脏数据、程序异常,SpringBoot 官方推荐使用 Bean Validation,今天就来介绍一下基础注解、实战使用,需要的朋友可以参考下

引言

在开发接口时,参数校验是必不可少的环节:前端传参是否为空、格式是否正确、数值是否合法,都需要后端严格校验,否则很容易出现脏数据、程序异常。

传统的 if-else 判空不仅代码臃肿,还容易遗漏,维护成本极高。

SpringBoot 官方推荐使用 Bean Validation(JSR-380) 实现优雅的参数校验,通过注解一键完成校验,配合全局异常处理,让接口更健壮、代码更简洁。

今天就来介绍一下基础注解、实战使用、分组校验、自定义注解、嵌套校验、全局异常处理

一、为什么要用 Bean Validation?

告别繁琐 if-else:不用写大量判空、判断逻辑,代码更简洁

注解式开发:一个注解完成一类校验,可读性极强

校验规则统一:团队协作无歧义

配合全局异常:校验失败自动返回友好提示,无需手动处理

支持复杂场景:分组校验、自定义校验、嵌套对象校验

二、核心依赖引入

SpringBoot 2.x 版本直接引入以下依赖即可:

<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-validationartifactId>
<dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<dependency>

三、最常用校验注解

1. 空与非空校验

@NotBlank:字符串不能为 null,且去除空格后长度大于0(专用字符串)

@NotNull:不能为 null,但可以是空字符串、空集合

@NotEmpty:不能为 null,且长度/大小大于0(字符串、集合、数组)

2. 数值校验

3. 格式校验

4. 日期与时间

四、单对象参数校验

1. 封装实体类 + 校验注解

importlombok.Data;
importjavax.validation.constraints.*;
/**
* 用户参数接收类
*/
@Data
publicclassUserDTO{
@NotBlank(message ="用户ID不能为空")
privateString userId;
@NotBlank(message ="用户名不能为空")
@Length(min =2, max =10, message ="用户名长度必须在2-10位之间")
privateString username;
@NotNull(message ="年龄不能为空")
@Min(value =18, message ="年龄必须大于等于18岁")
@Max(value =60, message ="年龄必须小于等于60岁")
privateInteger age;
@Email(message ="邮箱格式不正确")
@NotBlank(message ="邮箱不能为空")
privateString email;
@Pattern(regexp ="^1[3-9]\\d{9}$", message ="手机号格式不正确")
privateString phone;
}

2. Controller 开启校验(@Valid)

@Valid 是开启校验的核心注解,必须添加在参数前:

importorg.springframework.validation.BindingResult;
importorg.springframework.web.bind.annotation.PostMapping;
importorg.springframework.web.bind.annotation.RequestBody;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RestController;
importjavax.validation.Valid;
@RestController
@RequestMapping("/user")
publicclassUserController{
/**
* 新增用户
*/
@PostMapping("/add")
publicResult<String>addUser(@Valid@RequestBodyUserDTO userDTO){
// 校验通过,执行业务逻辑
returnResult.success("用户新增成功");
}
}

五、配合全局异常处理

参数校验失败会抛出 MethodArgumentNotValidException,我们在全局异常处理器中捕获,统一返回格式:

importlombok.extern.slf4j.Slf4j;
importorg.springframework.web.bind.MethodArgumentNotValidException;
importorg.springframework.web.bind.annotation.ExceptionHandler;
importorg.springframework.web.bind.annotation.RestControllerAdvice;
importjava.util.stream.Collectors;
@Slf4j
@RestControllerAdvice
publicclassGlobalExceptionHandler{
/**
* 捕获参数校验异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
publicResult<String>handleValidException(MethodArgumentNotValidException e){
// 拼接所有错误提示
String errorMsg = e.getBindingResult().getFieldErrors().stream()
map(error -> error.getField()+":"+ error.getDefaultMessage())
collect(Collectors.joining(";"));
        log.error("参数校验异常:{}", errorMsg);
returnResult.fail(400, errorMsg);
}
}

校验失败返回示例

{
"code":400,
"msg":"年龄必须大于等于18岁;邮箱格式不正确",
"data":null
}

六、分组校验

实际业务中,新增修改的校验规则不同:

使用分组校验可完美解决。

1. 定义分组接口

/**
* 新增分组
*/
publicinterfaceAddGroup{
}
/**
* 修改分组
*/
publicinterfaceUpdateGroup{
}

2. 实体类标注分组

@Data
publicclassUserDTO{
// 修改时必须传ID,新增时不需要
@NotBlank(message ="用户ID不能为空", groups =UpdateGroup.class)
privateString userId;
@NotBlank(message ="用户名不能为空", groups ={AddGroup.class,UpdateGroup.class})
privateString username;
}

3. Controller 指定分组

使用 @Validated 注解指定分组:

@RestController
@RequestMapping("/user")
@Validated
publicclassUserController{
// 新增:使用 AddGroup 分组校验
@PostMapping("/add")
publicResult<String>add(@Validated(AddGroup.class)@RequestBodyUserDTO userDTO){
returnResult.success("新增成功");
}
// 修改:使用 UpdateGroup 分组校验
@PostMapping("/update")
publicResult<String>update(@Validated(UpdateGroup.class)@RequestBodyUserDTO userDTO){
returnResult.success("修改成功");
}
}

七、自定义校验注解

当内置注解不满足业务时,可自定义注解,例如校验性别只能是男/女

1. 自定义注解@Gender

importjavax.validation.Constraint;
importjavax.validation.Payload;
importjava.lang.annotation.*;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy =GenderValidator.class)// 绑定校验器
public@interfaceGender{
Stringmessage()default"性别只能输入:男/女";
Class<?>[]groups()default{};
Class<?extendsPayload>[]payload()default{};
}

2. 自定义校验器

importjavax.validation.ConstraintValidator;
importjavax.validation.ConstraintValidatorContext;
publicclassGenderValidatorimplementsConstraintValidator<Gender,String>{
@Override
publicbooleanisValid(String value,ConstraintValidatorContext context){
// 校验逻辑
return"男".equals(value)||"女".equals(value);
}
}

3. 使用自定义注解

@Gender
privateString gender;

八、嵌套对象校验

如果参数是嵌套对象,需要在嵌套对象上添加 @Valid 才能开启校验:

@Data
publicclassUserDTO{
@NotBlank
privateString username;
@Valid// 开启嵌套校验
@NotNull(message ="地址信息不能为空")
privateAddressDTO address;
}
@Data
classAddressDTO{
@NotBlank(message ="详细地址不能为空")
privateString detail;
@NotBlank(message ="城市不能为空")
privateString city;
}

九、单个参数校验(非实体类)

如果接口是零散参数,在类上添加 @Validated,直接给参数加注解:

@RestController
@RequestMapping("/user")
@Validated
publicclassUserController{
@GetMapping("/get")
publicResult<String>getUser(
@NotBlank(message ="用户ID不能为空")String userId,
@NotNull(message ="状态不能为空")Integer status
){
returnResult.success("查询成功");
}
}

十、总结

  1. @Valid:开启实体类参数校验
  2. @Validated:开启分组校验、单个参数校验
  3. 常用注解@NotBlank@NotNull@Min@Max@Email
  4. 全局异常捕获:校验失败自动返回友好提示
  5. 分组校验:适配新增/修改不同规则
  6. 自定义注解:满足复杂业务校验

学会这套参数校验方案,你的接口健壮性、规范性、安全性直接拉满

以上就是SpringBoot接口参数校验(Bean Validation)实战指南的详细内容,更多关于SpringBoot接口参数校验的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文