描述
通常我们编写一个接口,参数校验这一步是必不可少的,如果传递的参数不符合规范,那么不应该进入到业务方法应该将不合法信息提示给前端。对于参数校验传统的做法是,每个接口在接收到参数后再手动判断是否合法,这样一来每个接口都要手动编写验证规则,很明显这部分工作可以独立出来做统一验证。
springboot的参数验证
为解决上述问题,springboot本身提供了一个验证框架。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
值得注意的是,在springboot2.3.x版本以后将这个依赖移除了,所以2.3以后的版本请手动添加,2.3以下的版本则不需要自己添加。
定义参数接受类并添加验证规则
import lombok.Data;
import lombok.ToString;
import javax.validation.constraints.Email;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
@Data
@ToString
public class User {
@NotEmpty(message = "姓名不能为空")
private String username;
@Min(value = 1 , message = "年龄不能小于1岁")
@Max(value = 100 , message = "年龄不能大于100岁")
private Integer age;
@Email
@NotEmpty(message = "邮箱不能为空")
private String email;
@NotEmpty(message = "地址不能为空")
private String address;
}
springboot的验证框架提供了一系列的注解用于验证参数,完整的注解可以去javax.validation.constraints
这个包下看。这里整理一下:
注解 | 说明 |
---|---|
@AssertFalse | 被注释的元素必须为 false |
@AssertTrue | 被注释的元素必须为 true |
@DecimalMax(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@DecimalMin(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Digits (integer, fraction) | 被注释的元素必须是一个数字,其值必须在可接受的范围内 |
@Null | 被注释的元素必须为 null |
@NotNull | 被注释的元素必须不为 null |
@Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@Size(max, min) | 被注释的元素的大小必须在指定的范围内 |
@Past | 被注释的元素必须是一个过去的日期 |
@Future | 被注释的元素必须是一个将来的日期 |
@Pattern(value) | 被注释的元素必须符合指定的正则表达式 |
定义一个controller来暴露接口
@RestController
public class UserController {
@PostMapping("/save")
public Result save(@RequestBody @Validated User user) {
return Result.success(user.toString());
}
}
接受参数User user
添加@Validated
注解,这样上面定义的规则才会生效。
给controller添加一个增强器
目的是为了拦截参数校验失败后的异常,然后统一结构返回。
@Slf4j
@RestControllerAdvice
public class ControllerAdvice {
/**
* 拦截表单参数校验
* @param e
* @return
*/
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler({BindException.class})
public Result bindException(BindException e) {
BindingResult bindingResult = e.getBindingResult();
String msg = Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage();
log.error("参数校验异常拦截:{}", msg);
return Result.error(msg);
}
/**
* 拦截JSON参数校验
* @param e
* @return
*/
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result bindException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
String msg = Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage();
log.error("参数校验异常拦截:{}", msg);
return Result.error(msg);
}
}
github地址:https://github.com/stryang/springboot/tree/master/spring-validated
展示部分效果如图