springboot中使用JSR-303完成数据校验

1、什么是JSR-303

JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation。

在任何时候,当你要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情。应用程序必须通过某种手段来确保输入进来的数据从语义上来讲是正确的。在通常的情况下,应用程序是分层的,不同的层由不同的开发人员来完成。很多时候同样的数据验证逻辑会出现在不同的层,这样就会导致代码冗余和一些管理的问题,比如说语义的一致性等。为了避免这样的情况发生,最好是将验证逻辑与相应的域模型进行绑定。
Bean Validation 为 JavaBean 验证定义了相应的元数据模型和 API。缺省的元数据是 Java Annotations,通过使用 XML 可以对原有的元数据信息进行覆盖和扩展。在应用程序中,通过使用 Bean Validation 或是你自己定义的 constraint,例如 @NotNull, @Max, @ZipCode, 就可以确保数据模型(JavaBean)的正确性。constraint 可以附加到字段,getter 方法,类或者接口上面。对于一些特定的需求,用户可以很容易的开发定制化的 constraint。Bean Validation 是一个运行时的数据验证框架,在验证之后验证的错误信息会被马上返回。

在这里插入图片描述

2、基础使用

1、引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2、在实体类中加上对应的校验注解

3、使用@Valid开启数据校验

在这里插入图片描述

4、创建统一的异常处理器

package com.itcxc.gulimall.product.exception;

import com.itcxc.common.exception.BizCodeEnume;
import com.itcxc.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;

/**
 * 全局异常处理器
 * @author chenxc
 * @date 2021/4/13 10:39
 */
@RestControllerAdvice
@Slf4j
public class ProductExceptionControllerAdvice {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R bindException(MethodArgumentNotValidException e) {
        BindingResult bindingR = e.getBindingResult();
        Map<String,String> map = new HashMap<>();
        for (FieldError fieldError : bindingR.getFieldErrors()) {
            map.put(fieldError.getField(),fieldError.getDefaultMessage());
        }
        return R.error(BizCodeEnume.VAILD_EXCEPTION.getCode(),BizCodeEnume.VAILD_EXCEPTION.getMsg()).put("data",map);
    }

    @ExceptionHandler(Exception.class)
    public R handleException(Exception e){
        log.error("异常信息:{}",e.getMessage());
        log.error("异常类型:{}",e.getClass());
        return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
    }

}

5、使用Postman请求

在这里插入图片描述
注:对象里面所有对象时要在里面也加注解
在这里插入图片描述

3、分组校验

1、创建分组的接口,不需要实现

/**
 * @author chenxc
 * @date 2021/4/13 11:41
 */
public interface AddGroup {
}
/**
 * @author chenxc
 * @date 2021/4/13 11:41
 */
public interface UpdateGroup {
}

2、将实体类的注解加上分组

在这里插入图片描述

3、将@Valid换为@Validated开启数据校验

注:@Valid 因为这个注解没有办法分组,所以使用Spring帮我们封装的@Validated选择分组
在这里插入图片描述

4、按顺序校验

1、声明一个验证序列,指定这个序列需要验证哪些组和验证的顺序


import javax.validation.GroupSequence;

@GroupSequence(value={
		AddGroup.class,
		UpdateGroup.class,
})
public interface ApplySequence {
}

2、使用@Validated开启数据校验

在这里插入图片描述

5、自定义校验

1、编写一个自定义的校验注解

注:该注解上的注解可以参考@Null这些已经实现的接口

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

/**
 * @author chenxc
 * @date 2021/4/13 16:11
 */
@Documented
@Constraint(
        validatedBy = {ListValueConstraintValidator.class}
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(ListValue.List.class)
public @interface ListValue {
    String message() default "{com.itcxc.common.valid.ListValue.message}";

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

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

    int[] vals() default {};

    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface List {
        ListValue[] value();
    }
}

2、编写一个自定义的校验器

校验器要实现接口ConstraintValidator <对应的的自定义注解,要标注的数据类型>

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

/**
 * @author chenxc
 * @date 2021/4/13 16:29
 */
public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {

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

    /**
     * 初始化方法
     * @param constraintAnnotation
     */
    @Override
    public void initialize(ListValue constraintAnnotation) {
        int[] vals = constraintAnnotation.vals();
        if (vals.length>0){
            for (int val : vals) {
                set.add(val);
            }
        }
    }

    /**
     * 判断校验是否成功
     * @param value 需要校验的值
     * @param constraintValidatorContext
     * @return
     */
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {
        return set.contains(value);
    }
}

3、关联自定义的校验器和自定义的校验注解

注:这个是在自定义注解上标注,指定要自定义校验器,并且校验器可以是多个

@Constraint(
        validatedBy = {ListValueConstraintValidator.class}
)

然后就像使用其他注解一样使用就好了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值