Java数据校验

  • Java
  • Java
大约 2 分钟

Maven依赖

 <dependency>
     <groupId>org.hibernate.validator</groupId>
     <artifactId>hibernate-validator</artifactId>
     <version>6.2.3.Final</version>
</dependency>

分组校验

当对同一个字段在不同情况下(不同方法)需要有不同的校验规则时,可以使用分组校验。

比如新增商品时禁止携带商品 id,需要使用 @Null 注解, 但是修改商品时必须携带商品 id,需要使用 @NotNull注解。

校验注解中一般都有 groups 属性:

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Repeatable(List.class)
@Documented
@Constraint(validatedBy = { })
public @interface Null {

	String message() default "{javax.validation.constraints.Null.message}";

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

	Class<? extends Payload>[] payload() default { };
    
	@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
	@Retention(RUNTIME)
	@Documented
	@interface List {

		Null[] value();
	}
}

可以设置 id 的校验注解如下:

@Null(message = "添加不能指定id", groups = {SaveGroup.class})
@NotNull(message = "修改需要指定id", groups = {UpdateGroup.class})
@TableId
private Long id;

其中 SaveGroupUpdateGroup 只是两个作为标识的接口

Controller层:

@RestController
public class GoodsController{
    @RequestMapping("/save")
    public Result save(@Validated({SaveGroup.class} @RequestBody Goods good)){
        ...
    }
    @RequestMapping("/update")
    public Result update(@Validated({UpdateGroup.class} @RequestBody Goods good)){
        ...
    }
}

自定义校验器

在项目中经常会遇到需要对前端传过来的参数进行校验,但是在使用正则表达式校验数值类型的字段时是不会生效的,比如下面这个案例就会报错:

@Pattern(regexp = "/^[0-1]$/", message="显示状态必须为0或1")
private Integer status;

这个时候可以使用自定义校验注解:

@EnumValidate(values={0,1}, group={SaveGroup.class, UpdateGroup.class})
private Integer status;

注解:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * @author 左齐亮
 * @version 1.0
 * 自定义校验注解
 * 1. @Constraint(validatedBy = { }) 可以指定该注解和校验器关联
 * 2. message() default "{}" 指定返回的错误信息--ValidationMessages.properties(Unicode格式)
 */
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {EnumConstraintValidator.class})
public @interface EnumValidation {
    String message() default "{com.njupt.valid.EnumValidation.message}";

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

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

    int[] values() default {};
}

需要注意的是注解的message属性值,这里填入的是 package name.EnumValidation.message,需要在Resources目录下建立ValidationMessages.properties文件,且需要转成Unicode编码格式:

com.njupt.valid.EnumValidation.message=\u663E\u793A\u72B6\u6001\u7684\u503C\u5FC5\u987B\u4E3A\u0030\u6216\u8005\u0031

校验器:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.HashSet;
import java.util.Set;

/**
 * @author 左齐亮
 * @version 1.0
 * 自定义校验器
 */
public class EnumConstraintValidator implements ConstraintValidator<EnumValidation, Integer> {

    private Set<Integer> set = new HashSet<>();

    @Override
    public void initialize(EnumValidation constraintAnnotation) {
        // 获取注解传入的values
        int[] values = constraintAnnotation.values();
        for (int value : values) {
            set.add(value);
        }
    }

    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        // 参数value是请求携带的参数值
        return set.contains(value);
    }
}
上次编辑于: