@validation

在实际开发中,需要对字段进行效验,通过使用if-else对请求的每一个参数一一效验,当效验的参数过多时,会有很多的if-else,代码不简洁,我们可以使用Spring提供的Validated,通过注解的形式完成效验。

注: SpringBoot 2.3.x 移除了validation依赖需要手动引入依赖

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

当效验不通过时,会抛出异常,这时可以使用统一异常处理对返回格式进行处理。

@Slf4j
@ControllerAdvice
public class ValidatedExceptionHandler {

    /**
     * 对于表单提交有效
     */
    @ResponseBody
    @ExceptionHandler(BindException.class)
    public String BindExceptionHandler(BindException e) {
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        List<String> msgList = new ArrayList<>();
        for (ObjectError allError : allErrors) {
            msgList.add(allError.getDefaultMessage());
        }
        return "【BindException】异常:" + msgList.toString();
    }

    /**
     * 对提交的方式为json格式有效
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public String exceptionHandler(MethodArgumentNotValidException exception) {
        BindingResult result = exception.getBindingResult();
        StringBuilder stringBuilder = new StringBuilder();
        if (result.hasErrors()) {
            List<ObjectError> errors = result.getAllErrors();
            if (errors != null) {
                errors.forEach(p -> {
                    FieldError fieldError = (FieldError) p;
                    stringBuilder.append(fieldError.getDefaultMessage());
                });
            }
        }
        return "【MethodArgumentNotValidException】异常:" + stringBuilder.toString();
    }

    /**
     * 对@RequestParam参数加@NotBlank、@NotNull、NotEmpty等
     */
    @ResponseBody
    @ExceptionHandler(value = ConstraintViolationException.class)
    public String ConstraintViolationExceptionHandler(ConstraintViolationException ex) {
        Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
        Iterator<ConstraintViolation<?>> iterator = constraintViolations.iterator();
        List<String> msgList = new ArrayList<>();
        while (iterator.hasNext()) {
            ConstraintViolation<?> cvl = iterator.next();
            msgList.add(cvl.getMessageTemplate());
        }
        return "【ConstraintViolationException】异常:" + msgList.toString();
    }
}

  • ConstraintViolationException:对@RequestParam参数加@NotBlank、@NotNull、NotEmpty等
@Validated
@RestController
@RequestMapping("/text")
public class TextController {

   @GetMapping("/validationNotEmpty")
   public String validationNotEmpty(@RequestParam("detailId") @NotEmpty(message = "detailId is not null") String detailId) {
       return "success";
   }

}

测试

9525866a23df6032dae23baea9537b8f.png

  • MethodArgumentNotValidException:对提交的方式为json格式有效
@RestController
@RequestMapping("/text")
public class TextController {

    @PostMapping("/validationNotEmpty")
    public String validationNotEmpty(@RequestBody @Validated OrderDetail orderDetail) {
        System.out.println(orderDetail.toString());
        return "success";
    }

}

 类

@Data
public class OrderDetail implements Serializable {

    private static final long serialVersionUID = 8105326778623039417L;

    @NotEmpty(message = "name is not null")
    private String name;

    @NotNull(message = "count is not null")
    @Max(value = 0, message = "不能为负数")
    private Integer count;

    @NotEmpty(message = "detail is not null")
    private String detail;

}

测试

866956ba9829abc64059f414ad6bedcc.png

  • BindException:对于表单提交有效
@RestController
@RequestMapping("/text")
public class TextController {

    @PostMapping("/validationNotEmpty")
    public String validationNotEmpty(@Validated OrderDetail orderDetail) {
        System.out.println(orderDetail.toString());
        return "success";
    }

}

测试

feb8679c1fad07d581b033c2f4a2fd20.png

常用注解:

a1737f24a75ece2b9ccf00c62292cb63.png

 分组

当多个接口使用同一个实体类,传的参数不同则效验也不同,或者有一些特殊的参数只有一个接口被使用,可以通过分组不同的接口使用不同的效验参数。

组:OneGroup

public interface OneGroup extends Default {}

 组:TwoGroup

public interface TwoGroup extends Default {}

@Data
public class OrderDetail implements Serializable {

    private static final long serialVersionUID = 8105326778623039417L;

    @NotEmpty(groups = OneGroup.class, message = "name is not null")
    private String name;

    @NotNull(groups = TwoGroup.class, message = "count is not null")
    private Integer count;

    @NotEmpty(message = "detail is not null")
    private String detail;

}

使用

@RestController
@RequestMapping("/text")
public class TextController {

    @PostMapping("/validationNotEmpty")
    public String validationNotEmpty(@Validated({OneGroup.class}) OrderDetail orderDetail) {
        System.out.println(orderDetail.toString());
        return "success";
    }

}

测试,因为使用的是第一组,所以count没有被效验。而detail没有规定组所以一直会被效验。 

1477e64181603652ab4aee8960efb098.png

 使用TwoGroup

@RestController
@RequestMapping("/text")
public class TextController {

    @PostMapping("/validationNotEmpty")
    public String validationNotEmpty(@Validated({OneGroup.class, TwoGroup.class}) OrderDetail orderDetail) {
        System.out.println(orderDetail.toString());
        return "success";
    }

}

测试,第二组也被使用,这时count也会被效验。

08d4f4bf2af8b9d06f77e4976fd9177b.png

也可以使用@Valid注解来实现参数的效验。

@Valid和@Validated区别:

  1. @Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制。而@Valid没有。
  2. @Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上。

    @Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上。

  3. @Validated:用在方法入参上无法单独提供嵌套验证功能。不能用在成员属性(字段)上,也无法提示框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。

    @Valid:用在方法入参上无法单独提供嵌套验证功能。能够用在成员属性(字段)上,提示验证框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值