spring-validation实现分组校验

文章目录

    • 前言
    • 实际开发可能会使用到分组校验
      • maven添加依赖
      • 简单使用
      • 高级应用分组
        • 自定义分组
        • 组合分组
      • 源码地址

前言

JSR 303中提出了Bean Validation,表示JavaBean的校验,Hibernate Validation是其具体实现,并对其进行了一些扩展,添加了一些实用的自定义校验注解。

​ Spring中集成了这些内容,你可以在Spring中以原生的手段来使用校验功能,当然Spring也对其进行了一点简单的扩展,以便其更适用于Java web的开发。

实际开发可能会使用到分组校验

写得有点凌乱,大家自己体会吧

maven添加依赖

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

简单使用

针对form表单提交或者@RequestBody加了@Validated方式,
内部可以使用

    @ApiModelProperty(value = "用户主键", required = true)
    @NotNull(message = "用户主键不能为空", groups = UpdateGroup.class)
    @NotBlank(message = "用户名不能为空", groups = UpdateGroup.class)
    private String userId;

    @ApiModelProperty(value = "用户名", required = true)
    @NotNull(message = "用户名不能为空", groups = {AddGroup.class, UpdateGroup.class})
    @NotBlank(message = "用户名不能为空", groups = {AddGroup.class, UpdateGroup.class})
    private String userName;

    @NotNull(message = "密码不能为空", groups = {AddGroup.class, UpdateGroup.class})
    @NotBlank(message = "密码不能为空", groups = {AddGroup.class, UpdateGroup.class})
    @ApiModelProperty(value = "密码", required = true)
    private String password;

    @NotNull(message = "性别不能为空", groups = {AddGroup.class, UpdateGroup.class})
    @ApiModelProperty(value = "性别", required = true)
    private GenderEnum gender;

其中有很多日常使用的规则注解如@Email@Url等等
还有下面列举的一些常规的检查
spring-validation实现分组校验_第1张图片
这边也可以组合hibernate-validator校验注解
spring-validation实现分组校验_第2张图片

注意如果想使用嵌套对象需要使用@Valid注解可以进行嵌套校验

高级应用分组

自定义分组

比如我很多时候新增和修改的DTO只是存在主键或者其他的一些少量字段差异而已,但是自己又不想去CV
首先swagger可以使用来忽略api文档的显示

    @ApiOperationSupport(ignoreParameters = "xxx")
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {

	/**
	 * Specify one or more validation groups to apply to the validation step
	 * kicked off by this annotation.
	 * 

JSR-303 defines validation groups as custom annotations which an application declares * for the sole purpose of using them as type-safe group arguments, as implemented in * {@link org.springframework.validation.beanvalidation.SpringValidatorAdapter}. *

Other {@link org.springframework.validation.SmartValidator} implementations may * support class arguments in other ways as well. */ Class<?>[] value() default {}; }

从源码可以知道@Validated支持组,那么我们就得去创建组比如我创建了
AddGroup

public interface AddGroup {}

// 第二种写法
public interface AddGroup extends Default {}
组合分组

理论的东西或者跟深层次的东西可以看源码。
核心这些是通过BeanPostProcessor后置处理器实现的
这个可以定义注解生效的顺序

@Target({ TYPE })
@Retention(RUNTIME)
@Documented
public @interface GroupSequence {

	Class<?>[] value();
}
@GroupSequence({UpdateGroup.class, UpdateExpensiveGroup.class})
public interface ComplexUpdateGroup {}

这边可以定义分组顺序,上述先进行UpdateGroup,再去进行UpdateExpensiveGroup

实现自定义的校验器

public class ValidUserConstraintValidator implements ConstraintValidator<ValidUser, UserDTO> {
    @Autowired
    private UserService userService;

    @Override
    public boolean isValid(UserDTO userDTO, ConstraintValidatorContext context) {
        String validResult = this.userService.valid(userDTO);
        if (StringUtils.isBlank(validResult)) {
            return true;
        }
        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(validResult).addConstraintViolation();
        return false;
    }
}

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
@Constraint(validatedBy = ValidUserConstraintValidator.class)
public @interface ValidUser {
    String message() default "用户已存在";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

@Data
@ApiModel("用户请求对象")
@ValidUser(groups = {AddGroup.class, UpdateGroup.class})
public class UserDTO implements Serializable {
    private static final long serialVersionUID = 6715147416524554153L;
    @ApiModelProperty(value = "用户主键", required = true)
    @NotNull(message = "用户主键不能为空", groups = UpdateGroup.class)
    @NotBlank(message = "用户名不能为空", groups = UpdateGroup.class)
    private String userId;

    @ApiModelProperty(value = "用户名", required = true)
    @NotNull(message = "用户名不能为空", groups = {AddGroup.class, UpdateGroup.class})
    @NotBlank(message = "用户名不能为空", groups = {AddGroup.class, UpdateGroup.class})
    private String userName;

    @NotNull(message = "密码不能为空", groups = {AddGroup.class, UpdateGroup.class})
    @NotBlank(message = "密码不能为空", groups = {AddGroup.class, UpdateGroup.class})
    @ApiModelProperty(value = "密码", required = true)
    private String password;

    @NotNull(message = "性别不能为空", groups = {AddGroup.class, UpdateGroup.class})
    @ApiModelProperty(value = "性别", required = true)
    private GenderEnum gender;

    public static User of(UserDTO userDTO) {
        return UserMapper.MAPPER.from(userDTO);
    }

    @Mapper
    interface UserMapper {
        UserMapper MAPPER = Mappers.getMapper(UserMapper.class);

        /**
         * DTO转DO
         *
         * @param userDTO DTO
         * @return DO
         */
        User from(UserDTO userDTO);
    }
}

源码地址

https://gitee.com/youxiaxiaomage/java-practices/tree/master/yxxmg-mybatis-plus-sample#mapstruct%E7%AE%80%E5%8C%96%E9%A2%86%E5%9F%9F%E5%AF%B9%E8%B1%A1dtodovo%E4%B9%8B%E9%97%B4%E7%9A%84%E8%BD%AC%E6%8D%A2

你可能感兴趣的:(spring,java,后端)