当前位置:网站首页>JRS303-数据校验

JRS303-数据校验

2022-08-11 06:54:00 花棉袄

🧑‍ 个人主页:花棉袄

本章内容:【JRS303-数据校验
版权: 本文由【花棉袄】原创在CSDN首发需要转载请联系博主

在这里插入图片描述

JRS303-数据校验

如果文章对你有帮助【关注点赞️收藏】

JSR303介绍

  • 在Java中提供了一系列的校验方式
  • 这些校验方式在“javax.validation.constraints”包中
  • 提供了如@Email,@NotNull等注解

1️⃣引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
  • 在非空处理方式上提供了@NotNull,@NotBlank和@NotEmpty

2️⃣常用注解

  • 所有校验注解都在:javax.validation.constraints包下

@NotNull

  • 注解元素禁止为null,能够接收任何类型

@NotEmpty

  • 该注解修饰的字段不能为null或""
  • 支持以下几种类型
集合长度的计算
Map (map size is evaluated)
map长度的计算
Array (array length is evaluated)
数组长度的计算

@NotBlank

  • 该注解不能为null,并且至少包含一个非空格字符
  • 接收字符序列

3️⃣开启校验

@Valid

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

🥌数据校验测试

  • 步骤1:实体类字段上使用校验注解 @NotNull @NotEmpty @NotBlank @Pattern
  • 步骤2:controller中加校验注解@Valid,开启校验
  • 步骤3:给校验的Bean后,紧跟一个BindResult,就可以获取到校验的结果,拿到校验的结果,就可以自定义的封装
public R save(@Valid @RequestBody BrandEntity brand, BindingResult result){
    }
  • 实体中添加注解
@Data
public class Student {
    
    @NotEmpty(message ="姓名不能为空")
    private String name;
}
  • controller层中保存方法添加:@Valid
@RestController
public class TestController {
    
    @RequestMapping("/test")
    public Result test(@Valid  @RequestBody Student student, BindingResult result) {
    
        String name = student.getName();
        HashMap<String, Object> map = new HashMap<>();
        map.put("name",name);
        map.put("errors",result.getFieldErrors());
         return Result.ok(map,"数据校验");
    }
}
  • 测试:http://localhost:8080/test
{
    
    "name":""
}
  • 返回信息
{
    
	"code": 200,
	"msg": "数据校验",
	"data": {
    
		"name": "",
		"errors": [
			{
    
				"codes": [
					"NotEmpty.student.name",
					"NotEmpty.name",
					"NotEmpty.java.lang.String",
					"NotEmpty"
				],
				"arguments": [
					{
    
						"codes": [
							"student.name",
							"name"
						],
						"arguments": null,
						"defaultMessage": "name",
						"code": "name"
					}
				],
				"defaultMessage": "姓名不能为空",
				"objectName": "student",
				"field": "name",
				"rejectedValue": "",
				"bindingFailure": false,
				"code": "NotEmpty"
			}
		]
	}
}

1️⃣自定义的封装错误信息

@RestController
public class TestController {
    
    @RequestMapping("/test")
    public Result test(@Valid @RequestBody Student student, BindingResult result) {
    
        String name = student.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 Result.fail(map, "数据校验");
        } else {
    
            return Result.ok(map);
        }
    }
}
  • 测试:http://localhost:8080/test
{
    
    "name":""
}
  • 错误信息
{
    
	"code": 500,
	"msg": "数据校验",
	"data": {
    
		"name": "姓名不能为空"	
	}
}

2️⃣统一异常处理

  • springmvc统一处理异常
@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
{
    
    "name":"",
}
  • 错误信息
{
    
	"code": 500,
	"msg": "数据校验出现问题",
	"data": {
    
		"name": "姓名不能为空"
	}
}

JSR303分组校验

1️⃣创建分组校验接口

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

2️⃣添加校验注解

@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;
}

3️⃣开启分组校验

  • @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岁"
	}
}

JSR303自定义校验

1️⃣编写自定义的校验注解

  • 比如要创建一个:@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]

2️⃣编写自定义的校验器


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

/** * @author Michale @EMail:[email protected] * @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;
    }
}

3️⃣关联校验器和校验注解

  • 在@ListValue注解关联校验器
@Constraint(validatedBy = {
     ListValueConstraintValidator.class})
一个校验注解可以匹配多个校验器

4️⃣添加自定义的校验注解

    @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]"
	}
}
原网站

版权声明
本文为[花棉袄]所创,转载请带上原文链接,感谢
https://blog.csdn.net/m0_46914264/article/details/126276710