文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-04-02 19:55

关注

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检查

长度检查

日期检查

数值检查

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

开启校验

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 {
    
    @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, "数据校验出现问题");
    }

    
    @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": "姓名不能为空"
	}
}

分组校验

创建分组校验接口


public interface NameGroup {
}

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;


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数据校验的资料请关注编程网其它相关文章!

 

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯