@Vaild,@Validated,@NotNull,@NotBlank,@NotEmpty史上最全用法以及各种踩坑细节

2023-04-10 17:17:56

首先常规用法

实体类中

    @ApiModelProperty(notes = "用户名称")
    @TableField(value = "user")
    @NotNull(message = "合同编号不能为空")
    @Length(max = 50,message = "最大长度不可超过50")
    private String user;

    @ApiModelProperty(notes = "用户编码")
    @TableField(value = "code")
    @NotNull(message = "编码不能为空")
    private String code;

controller层

	@PutMapping
    @ApiOperation(notes = "修改用户",value = "修改用户")
    public void updateUser(@RequestBody @Valid User vo){
    }

此处需要注意:
1.NotBlank,NotEmpty判断字符串不可判断字符串以外的类型,NotEmpty判断不为null和空串,NotBlank不为null和空串以及空格,NotNull不为null可判断所有类型
2.max,min只用来判断数字类型的比如Integer,BigDecimal,Decimal,double等并不是用来判断长度的,长度使用@Length




如果在不同场景下需要不同的校验可以这样

添加两个自定义接口

public interface Edit {
}
public interface Add {
}

实体类中

    @ApiModelProperty(notes = "用户名称")
    @TableField(value = "user")
    @NotNull(message = "合同编号不能为空", groups = {Add.class})
    @Length(max = 50,message = "最大长度不可超过50", groups = {Add.class, Edit.class})
    private String user;

    @ApiModelProperty(notes = "用户编码")
    @TableField(value = "code", groups = {Add.class})
    @NotNull(message = "编码不能为空", groups = {Add.class, Edit.class})
    private String code;

controller层

	@PutMapping
    @ApiOperation(notes = "修改用户",value = "修改用户")
    public void updateUser(@RequestBody @Validated({Edit.class}) User vo){
    }
	@PutMapping
    @ApiOperation(notes = "添加用户",value = "添加用户")
    public void addUser(@RequestBody @Validated({Add.class}) User vo){
    }

这样就可以实现不同场景下的不同调用

但是有时候我们不想在controller层校验,需要在service层校验该怎么办呢

实体类中写法不变service层这样


public interface UserService {
	public void addUser( @Valid User vo);
}

@Service
@Validated
public class UserServiceImpl implements UserService {
	public void addUser( @Valid User vo){}
}


千万注意实现类上的注解@Validated,如果需要不同需求不同校验同controller层使用group


如下

public void addUser( @Validated({Add.class}) User vo){}

还有一种场景比如当你批量导入的时候校验,需要在service层进行校验,注意这个时候使用this.是不好用的
比如


public void addUser( @Validated({Add.class}) User vo){}

public void exportUser( User vo){
	this.addUser(vo);
}

这是不好使的
需要这个样子


public void exportUser( User vo){
  		Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        //验证某个对象,,其实也可以只验证其中的某一个属性的
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(vo);
        for (ConstraintViolation<Object> constraintViolation : constraintViolations) {
            System.out.println(constraintViolation.getMessage());
        }
}

还有一种情况比如本次在controller层不想使用统一返回格式但是又想要校验,不想使用全局抛出的异常处理方式,所以调用service层校验

 		try {
            return Result.success(userService .updateContract(vo));
        } catch (ValidationException e) {
            e.printStackTrace();
            return Result.failure(e.getMessage());
        }catch (Exception e) {
            e.printStackTrace();
            return Result.failure(e.getMessage());
        }

这个时候就会发现返回是一整条
一条message
如果想只返回一条你会发现ValidationException这个异常debugger是可以看到参数的,但是取不出来,正确方式应该是


		try {
            return Result.success(userService .updateContract(vo));
        }catch (ConstraintViolationException e) {
            Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
            return failure(constraintViolations.iterator().next().getMessage(),null);
        }catch (Exception e) {
            e.printStackTrace();
            return Result.failure(e.getMessage());
        }

好了,大概就是这些用法,到此结束

  • 作者:一只努力的程序媛鸭
  • 原文链接:https://blog.csdn.net/yin_na/article/details/123601434
    更新时间:2023-04-10 17:17:56