Java利用自定义注解实现数据校验

2023-01-21 0 4,966

目录

JSR303介绍

Java中提供了一系列的校验方式

这些校验方式在javax.validation.constraints包中

引入依赖

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

常用注解

@Null 验证对象是否为null 

@NotNull 验证对象是否不为null, 无法查检长度为0的字符串 

@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格. 

@NotEmpty 检查约束元素是否为NULL或者是EMPTY.

Booelan检查

  • @AssertTrue 验证 Boolean 对象是否为 true 
  • @AssertFalse 验证 Boolean 对象是否为 false

长度检查

  • @Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内 
  • @Length(min=, max=) Validates that the annotated string is between min and max included.

日期检查

  • @Past 验证 Date 和 Calendar 对象是否在当前时间之前,验证成立的话被注释的元素一定是一个过去的日期 
  • @Future 验证 Date 和 Calendar 对象是否在当前时间之后 ,验证成立的话被注释的元素一定是一个将来的日期 
  • @Pattern 验证 String 对象是否符合正则表达式的规则,被注释的元素符合制定的正则表达式,regexp:正则表达式 flags: 指定 Pattern.Flag 的数组,表示正则表达式的相关选项。

数值检查

建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为”“,Integer为null 

  • @Min 验证 Number 和 String 对象是否大等于指定的值 
  • @Max 验证 Number 和 String 对象是否小等于指定的值 
  • @DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度 
  • @DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度 
  • @Digits 验证 Number 和 String 的构成是否合法 
  • @Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。 
  • @Range(min=, max=) 被指定的元素必须在合适的范围内 
  • @Range(min=10000,max=50000,message=”range.bean.wage”) 
  • @Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证) 
  • @CreditCardNumber信用卡验证 
  • @Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证。 
  • @ScriptAssert(lang= ,script=, alias=) 
  • @URL(protocol=,host=, port=,regexp=, flags=)

开启校验

controller中加校验注解@Valid,开启校验

数据校验测试

步骤1:实体类字段上使用校验注解 @NotNull @NotEmpty @NotBlank @Pattern

步骤2:controller中加校验注解@Valid,开启校验

步骤3:给校验的Bean后,紧跟一个BindingResult,就可以获取到校验的结果

public R save(@Valid @RequestBody User user, BindingResult result){}

实体中添加注解

@Data
public class Student {
    @NotEmpty(message =\"姓名不能为空\")
    private String name;
}

controller层中保存方法添加:@Valid

   @PostMapping(\"/jsr\")
    public AjaxResult testJrs(@Valid @RequestBody User user, BindingResult result) {
        String name = user.getName();
        HashMap<String, Object> map = new HashMap<>();
        map.put(\"name\", name);
        map.put(\"errors\", result.getFieldErrors());
        return AjaxResult.success(\"数据校验\", map);
    }

数据校验测试:测试:http://localhost:8080/test/jsr

@Data
public class User {

    @NotEmpty(message = \"姓名不能为空\")
    @ApiModelProperty(\"姓名\")
    private String name;

    @ApiModelProperty(\"学号\")
    private String id;

    @ApiModelProperty(\"年龄\")
    private String age;
}

返回信息

{
  \"msg\": \"数据校验\",
  \"code\": 200,
  \"data\": {
    \"name\": \"\",
    \"errors\": [
      {
        \"codes\": [
          \"NotEmpty.user.name\",
          \"NotEmpty.name\",
          \"NotEmpty.java.lang.String\",
          \"NotEmpty\"
        ],
        \"arguments\": [
          {
            \"codes\": [
              \"user.name\",
              \"name\"
            ],
            \"defaultMessage\": \"name\",
            \"code\": \"name\"
          }
        ],
        \"defaultMessage\": \"姓名不能为空\",
        \"objectName\": \"user\",
        \"field\": \"name\",
        \"rejectedValue\": \"\",
        \"bindingFailure\": false,
        \"code\": \"NotEmpty\"
      }
    ]
  }
}

自定义的封装错误信息

    @PostMapping(\"/package\")
    public AjaxResult testPackage(@Valid @RequestBody User user, BindingResult result) {
        String name = user.getName();
        Map<String, String> map = new HashMap<>();
        map.put(\"name\", name);
        if (result.hasErrors()) {
            //1.获取错误的校验结果
            result.getFieldErrors().forEach((item) -> {
                //2.获取发生错误时的message
                String message = item.getDefaultMessage();
                //3.获取发生错误的字段
                String field = item.getField();
                map.put(field, message);
            });
            return AjaxResult.error(\"数据校验\", map);
        } else {
            return AjaxResult.success(map);
        }
    }

自定义的封装错误信息:测试:http://localhost:80/test/package

{
  \"name\": \"\",
  \"id\": \"demoData\",
  \"age\": \"demoData\"
}

错误信息

{
  \"msg\": \"数据校验\",
  \"code\": 500,
  \"data\": {
    \"name\": \"姓名不能为空\"
  }
}

统一异常处理

@Slf4j
@RestControllerAdvice(basePackages = \"com.michale.jrs303.controllers\")
public class FireflyMallExceptionControllerAdvice {
    /**
     * 处理数据校验问题
     * @param e
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result handleVaildException(MethodArgumentNotValidException e) {
        log.error(\"数据校验出现问题:{},异常类型:{}\", e.getMessage(), e.getClass());
        BindingResult bindingResult = e.getBindingResult();
        Map<String, String> errorMap = new HashMap();
        bindingResult.getFieldErrors().forEach((fieldError) -> {
            errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());

        });
        return Result.fail(errorMap, \"数据校验出现问题\");
    }

    /**
     * 处理其他异常
     * @param throwable
     * @return
     */
    @ExceptionHandler(value = Throwable.class)
    public Result handleException(Throwable throwable) {
        return Result.fail();
    }
}
    @RequestMapping(\"/testException\")
    public Result testException(@Valid @RequestBody Student student) {
        String name = student.getName();
        Map<String, String> map = new HashMap<>();
        map.put(\"name\", name);
        return Result.ok(map);
    }

测试统一异常处理:测试:http://localhost:8080/testException

{
  \"msg\": \"数据校验出现问题\",
  \"path\": \"/test/testException\",
  \"code\": 414,
  \"errors\": {
    \"name\": \"姓名不能为空\"
  }
}

错误信息

{
	\"code\": 500,
	\"msg\": \"数据校验出现问题\",
	\"data\": {
		\"name\": \"姓名不能为空\"
	}
}

分组校验

创建分组校验接口

/**
 * @Author 天才小狐狸
 * @Data 2022/8/11 2:03
 * @Description 姓名校验分组
 */
public interface NameGroup {
}
/**
 * @Author 天才小狐狸
 * @Data 2022/8/11 2:04
 * @Description 年龄校验分组
 */
public interface AgeGroup {
}

添加校验注解

@Data
public class Student {
    @NotEmpty(message =\"姓名不能为空\",groups =  NameGroup.class)
    private String name;

    @NotEmpty(message =\"绰号不能为空\",groups = NameGroup.class)
    private  String nickName;

    @Min(value = 18,message = \"年龄下限不能低于18岁\" ,groups = AgeGroup.class)
    private String age;

    @Max(value = 60,message = \"年龄上限不能超过60岁\" ,groups = AgeGroup.class)
    private  String retireAge;
}

开启分组校验

@Validated(NameGroup.class)指定校验分组

@RequestMapping(\"/testGroup\")
    public Result testGroup(@Validated(NameGroup.class) @RequestBody Student student) {
        String name = student.getName();
        String nickName = student.getNickName();
        String age = student.getAge();
        String retireAge = student.getRetireAge();
        Map<String, String> map = new HashMap<>();
        map.put(\"name\", name);
        map.put(\"nickname\", nickName);
        map.put(\"age\", age);
        map.put(\"retireAge\", retireAge);
        return Result.ok(map);
    }

测试分组校验:http://localhost:8080/testGroup

{
    \"name\":\"\",
    \"nickName\":\"\",
    \"age\":\"17\",
    \"retireAge\":\"66\"
}

错误信息

{
	\"code\": 500,
	\"msg\": \"数据校验出现问题\",
	\"data\": {
		\"nickName\": \"绰号不能为空\",
		\"name\": \"姓名不能为空\"
	}
}

@Validated(AgeGroup.class)指定校验分组

@RequestMapping(\"/testGroup\")
    public Result testGroup(@Validated(AgeGroup.class) @RequestBody Student student) {
        String name = student.getName();
        String nickName = student.getNickName();
        String age = student.getAge();
        String retireAge = student.getRetireAge();
        Map<String, String> map = new HashMap<>();
        map.put(\"name\", name);
        map.put(\"nickname\", nickName);
        map.put(\"age\", age);
        map.put(\"retireAge\", retireAge);
        return Result.ok(map);
    }

测试分组校验:http://localhost:8080/testGroup

{
    \"name\":\"\",
    \"nickName\":\"\",
    \"age\":\"17\",
    \"retireAge\":66
}

错误信息

{
	\"code\": 500,
	\"msg\": \"数据校验出现问题\",
	\"data\": {
		\"retireAge\": \"年龄上限不能超过60岁\",
		\"age\": \"年龄下限不能低于18岁\"
	}
}

自定义校验

编写自定义的校验注解

比如要创建一个:@ListValue 注解,被标注的字段值只能是:0或1

@Documented
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ListValue {
    // 使用该属性去Validation.properties中取
    String message() default \"{com.atguigu.common.valid.ListValue.message}\";

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

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

    int[] value() default {};
}

设置错误信息:创建文件ValidationMessages.properties

 com.firefly.common.valid.ListValue.message=必须提交指定的值 [0,1]

编写自定义的校验器

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

/**
 * @author Michale @EMail:firefly@163.com
 * @Date: 2022/1/8 19:23
 * @Name ListValueConstraintValidator
 * @Description:
 */
public class ListValueConstraintValidator implements ConstraintValidator<ListValue, Integer> {
    private Set<Integer> set = new HashSet<>();

    @Override
    public void initialize(ListValue constraintAnnotation) {
        //获取注解允许的值
        int[] value = constraintAnnotation.value();
        for (int i : value) {
            set.add(i);
        }
    }

    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        //判断传入的值是否在满足允许的值
        boolean b = set.contains(value);
        return b;
    }
}

关联校验器和校验注解

在@ListValue注解关联校验器

@Constraint(validatedBy = { ListValueConstraintValidator.class})

一个校验注解可以匹配多个校验器

添加自定义的校验注解

    @ListValue(value = {0,1},groups = {AgeGroup.class,MyJRS303Group.class})
    private Integer gender;

测试自定义校验器:http://localhost:8080/testGroup

{
    \"gender\":\"3\"
}
{
	\"code\": 500,
	\"msg\": \"数据校验出现问题\",
	\"data\": {
		\"gender\": \"必须提交指定的值 [0,1]\"
	}
}

以上就是Java利用自定义注解实现数据校验的详细内容,更多关于Java数据校验的资料请关注其它相关文章!

 

:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可, 转载请附上原文出处链接。
1、本站提供的源码不保证资源的完整性以及安全性,不附带任何技术服务!
2、本站提供的模板、软件工具等其他资源,均不包含技术服务,请大家谅解!
3、本站提供的资源仅供下载者参考学习,请勿用于任何商业用途,请24小时内删除!
4、如需商用,请购买正版,由于未及时购买正版发生的侵权行为,与本站无关。
5、本站部分资源存放于百度网盘或其他网盘中,请提前注册好百度网盘账号,下载安装百度网盘客户端或其他网盘客户端进行下载;
6、本站部分资源文件是经压缩后的,请下载后安装解压软件,推荐使用WinRAR和7-Zip解压软件。
7、如果本站提供的资源侵犯到了您的权益,请邮件联系: 442469558@qq.com 进行处理!

猪小侠源码-最新源码下载平台 Java教程 Java利用自定义注解实现数据校验 http://www.20zxx.cn/463793/xuexijiaocheng/javajc.html

猪小侠源码,优质资源分享网

常见问题
  • 本站所有资源版权均属于原作者所有,均只能用于参考学习,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,建议提前注册好百度网盘账号,使用百度网盘客户端下载
查看详情

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务