Spring Boot 注解探秘:@Validated 开启数据验证之旅(下)

今天我们继续来探究自定义验证规则以及@Validated结合@RestControllerAdvice实现全局异常处理。

首先来看自定义验证规则。假设有一个场景,需要批量解绑手机号和微信, 为了确保请求数据的有效性和一致性,我们应当如何对请求参数进行严格的校验呢?

首先,创建用于数据验证的实体类。

@Data
public class Account{
    
    @NotBlank(message = "手机号不能为空")
    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
    private String phone;
    
    @NotBlank(message = "微信号不能为空")
    private String weChat;
}

接下来,在controller层,定义处理解绑请求的方法。

@RequestMapping("/account")
@Validated
public class Demo{
    @PostMapping("/unbind")
    Response<?> unbind(@valid @ValidUnbindAccount @RequestBody List<Account> list){ 
        ……               
    }
}

这里简单聊聊@Validated和@Valid的差异。

  • @Validated支持更细粒度的方法参数级别的校验,同时其针对多场景,可以采用分组校验。
  • @Valid是面向整个对象做校验。以下是代码示例。
@RequestMapping("/account")
@Validated
public class Demo{
    // @Valid针对对象使用
    @PostMapping("/unbind")
    Response<?> unbind(@valid @ValidUnbindAccount @RequestBody List<Account> list){ 
        ……               
    }
    
    // @Validated 具体参数可用
    @GetMapping("/getWechat")
    Response<String> getWechat(@NotBlank(message = "用户ID不能为空") String userId){ 
        ……               
    }
}

然后,创建@ValidUnbindAccount注解。

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validateBy = UnbindAccountValidator.class)
public @interface ValidUnbindAccount {
    String message() default "",
    Class[] group() default {},
    Class<? extends Payload>[] payload() default {};
}

紧接着,创建对应的验证器UnbindAccountValidator类。

public class ValidUnbindAccount implements ConstraintValidator<ValidUnbindAccount, List<Account>>{
    
    @Override
    public boolean isValid(List<Account> accountList, ConstraintValidatorContext constraintValidatorContext) {
    if(ObjectUtils.isEmpty(accountList) || accountList.size() < 1){
        return false;
    }
    // 手机号准确性或者微信号准确性的更多细节校验逻辑可以放到这里, 欢迎大家评论区探讨。
    return true;
}

最后,通过@RestControllerAdvice创建全局异常处理类。

@RestControllerAdvice
public class GlobalExceptionHandler{

    @ResponseBody
    @ExceptionHandler(Throwable.class)
    public Response<?> handleException(Throwable ex){
        if(e instanceof MethodArgumentNotValidException){
           String msg = ex.getBindingResult().getFieldErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(","))
           return Response.fail(HttpStatus.BAD_REQUEST.value(), msg)
        }
        if(e instanceOf BizRuntimeException){
           return Response.fail(ex.getMessage())
        }
    }
}

当向/account/unbind接口发送请求时,如果传入的list为空或者list的size< 1都会抛出

MethodArgumentNotValidException异常。全局异常处理类会捕获这个异常,并将错误信息以 JSON 格式返回给客户端,状态码为400 Bad Request。此外,如果urI找不到或者请求到达service层处理时发生异常(如数据索引越界,空指针异常等),全局异常处理类业会捕获该异常,并响应给客户端。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值