SpringBoot Validator参数校验

SpringBoot Validator参数校验,第1张

SpringBoot Validator参数校验

      • 前言
      • 一. SpringBoot 集成参数校验
        • 1. 引入依赖
        • 2. 定义要进行参数校验的实体类
        • 3. 定义校验类进行测试
        • 4. 查看结果
        • 5.统一异常处理器
          • 6. 查看响应结果
      • 二. 自定义参数校验
        • 1. 创建自定义校验注解 EnumValue
        • 2. 创建 EnumValue 校验注解处理类 EnumValuevalidator
        • 3. 在字段上添加注解
        • 4. 查询响应结果
      • 三. 分组校验
        • 1. 定义分组接口
        • 2. 在模型中给参数添加分组
        • 3. 给需要参数校验的方法指定分组
        • 4. 查看响应结果

前言

  在日常开发过程中, 我们要对前端传过来的参数进行验证,防止一些非法参数对我们的业务造成影响。例如:登录的是否需要校验用户名密码是否为空,发送短信的时候要校验手机号格式是否正确,这个时候如果去用 if else 去一个个进行校验的就比较繁琐,代码的可读性就比较差
Validator 框架就是为了解决开发人员在开发的少写代码,注重业务逻辑的开发,validation 主要是校验用户提交的数据的合法性,比如是否为空,密码是否符合规则,邮箱格式是否正确等等…

一. SpringBoot 集成参数校验 1. 引入依赖

  org.springframework.boot
  spring-boot-starter-web



  org.springframework.boot
  spring-boot-starter-validation

2. 定义要进行参数校验的实体类
@Data
public class User {
    private String id;

    @Length(min = 11,max = 11,message = "手机号格式不正确")
    private String phone;

    @NotBlank(message = "名字为必填项")
    private String name;

    @Email(message = "请填写正确的邮箱地址")
    private String email;
	@NotEmpty(message = "性别不能为空")
    private String sex;

	@NotNull(message = "年龄不能为空")
    private Integer age;
}

常见的约束注解有:

注解功能@NotNull不能为null,可以是空@Max最大不得超过此最大值@Min最大不得小于此最小值@NotBlank字符串不能为null,字符串trim()后也不能等于"" 3. 定义校验类进行测试
@RestController
@Slf4j
@Validated
public class ValidController {

	
    @PostMapping("/test1")   
    public String test1(@Validated @RequestBody User user){
        return "test1 valid success";
    }

	 
    @PostMapping("/test2")
    public String test2(@Validated User user){
        return "test2 valid success";
    }
  
  	
    @PostMapping("/test3")
    public String test3(@Email String email){
        return "email valid success";
    }
}
4. 查看结果
  1. 调用 test1 方法,查看响应
POST http://localhost:8080/test1
Content-Type: application/json

{
  "id": 1,
  "name": "十一",
  "email": "898963",
  "sex": "0",
  "age": 22
  }
{
  "status": 500,
  "message": "Validation failed for argument [0] in public java.lang.String com.fox.controller.ValidController.test1(com.fox.domain.User): [Field error in object 'user' on field 'email': rejected value [898963]; codes [Email.user.email,Email.email,Email.java.lang.String,Email]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.email,email]; arguments []; default message [email],[Ljavax.validation.constraints.Pattern$Flag;@7476422b,org.springframework.validation.beanvalidation.SpringValidatorAdapter$ResolvableAttribute@78dedd82]; default message [请填写正确的邮箱地址]] ",
  "data": null,
  "timestamp": 1628239624332
}
  1. 调用test2方法,提示的是org.springframework.validation.BindException异常
POST http://localhost:8080/test2
Content-Type: application/x-www-form-urlencoded

id=1&name=11&email=12345678&sex=0&age=22
{
  "status": 500,
  "message":  "org.springframework.validation.BeanPropertyBindingResult: 1 errorsnField error in object 'user' on field 'email': rejected value [12345678]; codes [Email.user.email,Email.email,Email.java.lang.String,Email]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.email,email]; arguments []; default message [email],[Ljavax.validation.constraints.Pattern$Flag;@7476422b,org.springframework.validation.beanvalidation.SpringValidatorAdapter$ResolvableAttribute@5116f8f3]; default message [请填写正确的邮箱地址]",
  "data": null,
  "timestamp": 1637489707831
}
  1. 调用test3方法,提示的是javax.validation.ConstraintViolationException异常
POST http://localhost:8080/test3
Content-Type: application/x-www-form-urlencoded

email=3123123
{
  "code": 500,
  "message": "test3.email: 不是一个合法的电子邮件地址",
  "data": null,
  "timestamp": 1637489904002
}

通过加入 Validator 校验框架可以帮助我们自动实现参数的校验。

5.统一异常处理器

Validator 校验框架返回的错误提示不方便阅读,为了便于阅读,我们需要对其进行简化。

   
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResultData validationErrorHandler(MethodArgumentNotValidException ex) {
        String message = ex.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        return ResultData.fail(message);
    }

    
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public ResultData validationErrorHandler(BindException ex) {
        String message = ex.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        return ResultData.fail(message);
    }

    
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public ResultData validationErrorHandler(ConstraintViolationException ex) {
        String message = ex.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
        return ResultData.fail(message);
    }
6. 查看响应结果
POST http://localhost:8080/test1
Content-Type: application/json

{
  "id": 1,
  "name": "十一",
  "email": "898963",
  "sex": "0",
  "age": 22
}
{
    "code": 500,
    "message": "请填写正确的邮箱地址",
    "data": null,
    "timestamp": 1637490231626
}
二. 自定义参数校验 1. 创建自定义校验注解 EnumValue
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@documented
@Constraint(validatedBy = {EnumValuevalidator.class})
public @interface EnumValue {

    // 默认错误消息
    String message() default "必须为指定值";

    String[] strValues() default {};

    int[] intValues() default {};

    // 分组
    Class[] groups() default {};

    // 负载
    Class[] payload() default {};

    // 指定多个时使用
    @Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @documented
    @interface List {
        EnumValue[] value();
    }
}
2. 创建 EnumValue 校验注解处理类 EnumValuevalidator
public class EnumValuevalidator implements ConstraintValidator {

    private String[] strValues;
    private int[] intValues;

    @Override
    public void initialize(EnumValue constraintAnnotation) {
        strValues = constraintAnnotation.strValues();
        intValues = constraintAnnotation.intValues();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        if (value instanceof String) {
            for (String s : strValues) {
                if (s.equals(value)) {
                    return true;
                }
            }
        } else if (value instanceof Integer) {
            for (int s : intValues) {
                if (s == ((Integer) value).intValue()) {
                    return true;
                }
            }
        }
        return false;
    }
}
3. 在字段上添加注解
@ApiModelProperty(value = "性别")
@EnumValue(strValues = {"0","1"}, message="性别只能是0或者1")
private String sex;
4. 查询响应结果
{
    "code": 500,
    "message": "性别只能是0或者1",
    "data": null,
    "timestamp": 1637490878327
}
三. 分组校验

在实际开发中,难免遇到对一个实体类的一些属性,不同的请求会有不同的校验规则的场景。比如:用户注册时,User 类的 id 需要校验为空,因为 User 的 id 肯定是由系统维护而不是让用户自己填写,但是在修改密码的时候,又需要传入 id 去作为条件更新,此时,分组校验就派上用场了。

1. 定义分组接口
public class ValidationGroups {
    public interface insert {
    }
 
    public interface update {
    }
 
}
2. 在模型中给参数添加分组
public class User {
    @NotBlank(groups = ValidationGroups.update.class)
    @Null(groups = ValidationGroups.insert.class)
    private int id;
}
3. 给需要参数校验的方法指定分组
@ApiOperation("新增")
    @PostMapping("/add")
    public String add(@Validated(value = ValidationGroups.insert.class) User user){
        return "success";
    }
4. 查看响应结果
POST http://localhost:8080/add
Content-Type: application/application/json

{
  "name": "十一",
  "email": "18790334713@163.com",
  "sex": "0",
  "age": 22
}

在 insert 时我们没有传递 id参数,校验通过。

当我们使用同样的参数调用 update 方法时则提示参数校验错误。

{
    "code": 500,
    "message": "id不能为空",
    "data": null,
    "timestamp": 1637491548612
}

代码地址: https://gitee.com/mingyangliang/spring-boot-validated

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5575952.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-14
下一篇2022-12-14

发表评论

登录后才能评论

评论列表(0条)

    保存