1 概述
后台单独对接收到的参数进行验证时比较麻烦,springboot项目的web组件(spring-boot-starter-web)集成了hibernate-validator,开发者可以直接使用hibernate-validator提供的注解对数据进行校验,当有一些复杂的参数校验时我们也可以自定义校验注解
2 添加依赖
<dependencies>
<!-- 唯一需要依赖,默认就内嵌了Tomcat容器,如需要更换容器Jetty、Undertow也极其简单-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--该依赖只会在编译时调用-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
</dependencies>
3 自定义注解
定义一个@DateTime注解
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = DateTimeValidator.class)
public @interface DateTime {
String message() default "格式错误";
String format() default "yyyyMM";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@Constraint,指定校验类
message,失败提示信息
groups,分组验证(后面介绍)
payload,不知道,欢迎留言探讨
4 实现具体验证类
技巧01:必须实现ConstraintValidator接口
技巧02:实现了ConstraintValidator接口后即使不进行Bean配置,spring也会将这个类进行Bean管理
技巧03:可以在实现了ConstraintValidator接口的类中依赖注入其它Bean
本文源码技巧04:实现了ConstraintValidator接口后必须重写 initialize 和 isValid 这两个方法;initialize方法主要来进行初始化,通常用来获取自定义注解的属性值;isValid 方法主要进行校验逻辑,返回true表示校验通过,返回false表示校验失败,通常根据注解属性值和实体类属性值进行校验判断
public class DateTimeValidator implements ConstraintValidator<DateTime, String> {
private DateTime dateTime;
@Override
public void initialize(DateTime dateTime) {
this.dateTime = dateTime;
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// 如果 value 为空则不进行格式验证,为空验证可以使用 @NotBlank @NotNull @NotEmpty 等注解来进行控制,职责分离
if (value == null) {
return true;
}
String format = dateTime.format();
if (value.length() != format.length()) {
return false;
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
try {
simpleDateFormat.parse(value);
} catch (Exception e){
return false;
}
return true;
}
}
实现ConstraintValidator接口,定义initialize和isValid方法。
- initialize,主要用于初始化,它可以获得当前注解的所有属性
- isValid,进行约束验证的主体方法,其中 value 就是验证参数的具体实例,context 代表约束执行的上下文环境。
5 实体类
@Lenth(min=,max=)只适应于字符串
@Size(min=,max=)可以是字符串,数组,集合,Map
@Data
public class User {
@NotNull(message = "名字不能为空")
@Size(min = 4, max = 10, message = "name 长度必须在 {min} - {max} 之间")
private String name;
@NotNull(message = "生日不能为空")
@DateTime(format = "yyyyMMdd", message = "格式错误,正确格式为:yyyyMMdd")
private String birthday;
}
6 控制层
6.1 如何使参数校验生效
在控制层方法的形参前面添加@Valid注解或@Validated
6.2 利用BindingResult对象获取参数错误字段和参数错误信息
技巧01:如果只是添加@Valid注解,如果参数错误就会直接抛出异常
技巧02:后台开发时通常都需要对前端传过来的参数进行一次参数验证,如果参数不正确我们需要抛出一些用户可以识别的错误信息而不是抛出原生的错误;所以我们需要在方法中添加一个BindingResult参数
技巧03:给控制方法添加了BindingResult参数后,即使前端传过来的参数不合法也会继续执行方法体;我们可以利用BindingResult对象去判断时哪一个参数不合法,从而抛出一些自定义的异常信息
@RestController
public class UserController {
@PostMapping("/user")
public R addUser(@Validated @RequestBody User user, BindingResult br) {
if (br.hasErrors()) {
return R.isFail().msg(br.getFieldError().getDefaultMessage());
} else {
return R.isOk().data(user);
}
}
}
技巧04:利用BindingResult对象的hasErrors方法判断是否有参数错误
技巧05:利用BindingResult对象的getFieldErrors方法获取所有有参数错误的属性
技巧06:利用错误属性对象的getDefaultMessage去获取错误提示信息
7 测试结果
8 工程目录
9 结束语
说点什么呢,有任何建议,欢迎留言探讨,本文源码。
---------------------
作者:Mkeeper
来源:CSDN
原文:https://blog.csdn.net/liu19900205/article/details/81503511
版权声明:本文为博主原创文章,转载请附上博文链接!