您当前的位置: 首页 > 

陈橙橙丶

暂无认证

  • 1浏览

    0关注

    107博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

使用@Constraint配合自定义注解开发

陈橙橙丶 发布时间:2020-06-01 09:05:00 ,浏览量:1

前言

通常我们在开发的过程中,需要对前端传入的数据进行校验,尽管这一步已经在前端进行了一次校验,虽然现在已经有了很多校验的注解,@NotNull、@NotBlank、@URL等一系列注解帮助我们进行校验,但是在实际的业务开发过程中,这些可能不足以满足我们的需求,这时候我们就需要自己来定义注解了。

可能需要用到的依赖按需导入:

		
            org.hibernate
            hibernate-validator
            5.4.1.Final
        
        
            org.jboss.logging
            jboss-logging
            3.3.0.Final
        
        
            com.fasterxml
            classmate
            1.3.3
        
@Constraint

这个注解的主要作用就是帮助我们来处理验证逻辑的,根据根据自己的业务需求来完成这一块验证的逻辑。下面我们就来简单测试一下。

**场景 **:假设我们一个实体类的属性如下解释,我们需要对前端传入的数字是不是0或1。

/**
     * 显示状态[0-不显示;1-显示]
     */
    private Integer showStatus;
定义注解
@Documented
@Constraint(validatedBy = {ListValueConstraintValidator.class})
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER,ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ListValue {
   
    String message() default "{com.atguigu.common.valid.ListValue.message}";

    Class[] groups() default {};
    
	int[] vals() default {};
	
    Class[] payload() default {};

    
}

message():错误信息,如果我们没有在注解中定义错误信息的话,他会默认去寻找com.atguigu.common.valid.ListValue.message为key的错误信息 groups():这个主要是来进行分组验证的。 ** vals() ** :自行定义的值

我们可以看到@Constraint中 @Constraint(validatedBy = {ListValueConstraintValidator.class}) 这段意思是我们将此注解的验证逻辑交给ListValueConstraintValidator来处理,这里是一个数组,我们可以传入多个处理逻辑。

ConstraintValidator接口,它有两个泛型,第一个是自定义的注解类,第二个就是要验证的数据的类型,这两个类里面都有两个方法,initialize和isValid,第一个是初始化方法,第二个是验证的逻辑方法,返回true,则验证通过,否则则不通过。

ListValueConstraintValidator自定义验证逻辑
public class ListValueConstraintValidator implements ConstraintValidator {

    private Set set = new HashSet();
    /**
     * 初始化 加载注解的信息。也就是带有此注解Bean上的vals值
     * @param constraintAnnotation
     */
    @Override
    public void initialize(ListValue constraintAnnotation) {
        int[] vals = constraintAnnotation.vals();
        for (int val : vals) {
            set.add(val);
        }
    }

    /**
     * 判断是否校验成功
     * @param value 需要校验的值 实际传入的值
     * @param context 上下文信息
     * @return
     */
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {

        return set.contains(value);
    }
}

** ValidationMessages.properties **

规范(JSR303)说,我必须将ValidationMessages.properties放到我的类路径根目录中,我希望它应该是MyDeploymentUnit.war / WEB-INF / classes / ValidationMessages.properties,这就是我的应用程序的构建和部署方式。出于调试原因,我将此代码添加到了自定义验证器中,以确保文件存在并正确设置。

在这里插入图片描述 key就是我们在注解定义的默认 message的值。

测试

在Controller中需要进行校验的Bean加上 ** @Validated ** 注解 在这里插入图片描述

需要验证的 属性 在这里插入图片描述 这里的如果校验不通过的话,他会抛出一个异常,我们只需要捕获到这个错误信息即可。 在这里插入图片描述

如果我们去掉属性声明的message信息 他会去寻找默认的ValidationMessages.properties下的信息。

在这里插入图片描述

分组校验

可能大家会注意到我在Controller中使用 @Validated 注解时会带有一个value值,他的作用是对操作进行分组。比如请看如下

	@NotNull(message = "修改商品时请传入商品id",groups = {UpdateGroup.class})
    @Null(groups = {AddGroup.class},message = "不能指定id")
    @TableId
    private Long brandId;

商品的数据表的对应的ID,我们可能在进行新增操作时无需我们来指定对应的ID,因为我们一般设置都会默认自增的。而我们在查询或者更新的时候可能会根据ID来查出这一条记录。总的来说的就是在进行更新时需要ID,新增不需要。每一个注解都会带有groups这个属性来声明自己的组。

如何使用呢? 很简单:

定义对应的接口或者类。

public interface AddGroup {
}
// ------------------------------
public interface UpdateGroup {
}
//---------------------------------
public interface UpdateStatusGroup {
}

我们只需要定义三个接口来声明组,无需任何操作。

在Controller中的@Validated 注解中声明对那个组进行验证。

@RequestMapping("/save")
    public R save(@Validated(value = {AddGroup.class}) @RequestBody BrandEntity brand) {
        brandService.save(brand);
        return R.ok();
    }

实体类进行分组逻辑

	@NotNull(message = "修改商品时请传入商品id",groups = {UpdateGroup.class})
    @Null(groups = {AddGroup.class},message = "不能指定id")
    @TableId
    private Long brandId;

验证: 新增时:传入ID会失败 在这里插入图片描述

更新时:不传ID 会失败 在这里插入图片描述

关注
打赏
1648473527
查看更多评论
立即登录/注册

微信扫码登录

0.0371s