@Vaild的作用及其用法
在编写接口的时候,通常会进行参数的校验,一般方法就是if语句的疯狂叠加,逻辑上是可以的,没什么问题,但是代码这样就很乱,感觉一团一样,而且不同的地方有些相似的校验还得重写,如下。
·
一、@Valid使用背景
在编写接口的时候,通常会进行参数的校验,一般方法就是if语句
的疯狂叠加,逻辑上是可以的,没什么问题,但是代码这样就很乱,感觉一团一样,而且不同的地方有些相似的校验还得重写,如下。
@PostMapping("/user")
public String addUserInfo(@RequestBody User user) {
if (user.getName() == null || "".equals(user.getName()) {
......
} else if(user.getSex() == null || "".equals(user.getSex())) {
......
}
}
二、@Valid 作用
- @Valid 的主要作用是用于数据效验,主要用法是:
- 在实体中的属性上,添加不同的注解(如下)来完成不同的校验。
- 在接口类中的接收数据参数中添加 @Valid 注解。
- 实体注解详解:
@NotEmpty
:元素值不为null且不为空(字符串长度不为0、集合大小不为0)@NotBlank
:验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格。@Null
:只能为null@NotNull
:不为null@Email
:验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式@AssertFalse
:必须为false@AssertTrue
:必须为true@DecimalMax(value)
:不大于指定值的数字DecimalMin(value)
:不小于指定值的数字@Digits(integer,fraction)
:一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction@Max(value)
:不大于指定值的数字@Min(value)
:不小于指定值的数字@Future
:必须是一个将来的日期(不包含现在)@FutureOrPresent
:必须是一个将来的日期(包含现在)@Past
:必须是一个过去的日期(不包含现在)@PastOrPresent
:必须是一个过去的日期(包含现在)@Pattern(value)
:符合指定的正则表达式@Size(max,min)
:限定字符长度在min到max之间@Positive
:数值是否是正数@PositiveOrZero
:数值是否是正数和0@Negative
:数值是否是负数@NegativeOrZero
:数值是否是负数和0
注意
- 实体类验证只是针对该实体,如果 该实体 存在 成员变量 为 实体类 ,则需要在该成员变量(假设你需要验证该实体内的变量)上加
@Valid 注解
。 - @Valid 对 Get 请求中接收的平面参数请求无效。
二、@Valid 用法(导错包不生效)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
此包下的
import javax.validation.constraints
2.1、实体属性添加
1.单个实体
public class User {
@NotBlank(message = "用户名不为空")
private String username;
@NotBlank(message = "密码不为空")
private String password;
}
2.嵌套实体
public class User {
@NotBlank(message = "用户名不为空")
private String username;
@NotBlank(message = "密码不为空")
private String password;
@Valid //不加此注解,则不会校验
@NotNull(message = "用户住址不能为空")
private Address address;
}
public class Address {
@NotBlank(message = "地址详情不能为空")
private String info;
}
2.2、接口添加
@PostMapping("/user")
public void addUserInfo(@RequestBody @Valid User user) {
}
2.3、全局异常捕获
@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)//最高优先级,防止有其他的全局异常捕获导致这个无法捕获
public class ExceptionAdvice {
@ExceptionHandler(value = {MethodArgumentNotValidException.class})
public R handleValidException(MethodArgumentNotValidException m){
Map<String,String> errorMsg = m.getBindingResult.getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField,FieldError::getDefaultMessage,(k1,k2) -> k1));
return R.FAILED("数据异常").setData(errorMsg);
}
}
三、分组
分组是在实体类验证中常用的一种技术,它允许你根据不同的场景对验证规则进行分组,从而在不同的情况下应用不同的验证规则。
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class UserCopyVo {
@NotEmpty(groups = update.class, message = 'id不能为空')
private String id;
@NotEmpty()
private String userName;
private String avatar;//头像
public UserCopyVo(UserEntity user) {
this.userName = user.getUserName();
this.id = user.getUuid();
this.avatar = user.getAvatar();
}
/**
* 设置分组
*/
public interface add extends Default {
}
public interface update extends Default {
}
}
@ApiOperation(value = 'test', notes = 'test action')
@PostMapping('/test')
public String test(@Validated(UserCopyVo.update.class) @RequestBody UserCopyVo u) {
System.out.println(u);
return 'success0000';
}
四、@Valid拓展
有的时候,我们发现@Valid
的一些注解无法满足我们的特殊开发需求,那就需要对其注解进行拓展了。
要拓展@Valid注解,可以按照以下步骤进行操作:
4.1、创建一个自定义的注解
用@Constraint
注解来定义这个自定义注解,并指定一个自定义的校验器类。
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = AnnotateValidator.class)
public @interface Annotate{
String message() default "Invalid value";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
4.2、创建一个自定义的校验器类
创建自定义校验器类实现ConstraintValidator
接口,并重写initialize
和isValid
方法。
public class AnnotateValidator implements ConstraintValidator<Annotate, String> {
@Override
public void initialize(Annotate annotation) {
// 初始化校验器,可以空着
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// 执行自己的校验逻辑,返回布尔值即可
return value != null && value.startsWith("custom");
}
}
CustomValidator
校验器类实现了ConstraintValidator<CustomValid, String>
接口,其中CustomValid
是自定义注解的类型,String
是要校验的值的类型。
4.3、测试
在需要校验的字段或方法参数上使用自定义的注解。
public class Test{
@CustomValid(message = "参数格式不对")
private String customField;
}
public class MyController {
@PostMapping("/myEndpoint")
public void myEndpoint(@Valid @RequestBody Test myTest) {
// ...
}
}
更多推荐
已为社区贡献2条内容
所有评论(0)