SpringBoot实战:validator参数校验及捕捉详细教程(附git源码)



简介

项目中只要在Java Bean上放一些校验注解,就可以实现校验支持,杜绝通篇 if else 参数判断,而且这个校验是支持group的概念的,对于不同的group生效的校验不一样。这个很有用,因为对于增删改查等不同的操作,需要执行的校验本来就是不一样的。

常用注解解析:

  • @AssertFalse 可以为null,如果不为null的话必须为false

  • @AssertTrue 可以为null,如果不为null的话必须为true

  • @DecimalMax 设置不能超过最大值

  • @DecimalMin 设置不能超过最小值

  • @Digits 设置必须是数字且数字整数的位数和小数的位数必须在指定范围内

  • @Future 日期必须在当前日期的未来

  • @Past 日期必须在当前日期的过去

  • @Max 最大不得超过此最大值

  • @Min 最大不得小于此最小值

  • @NotNull 不能为null,可以是空

  • @Null 必须为null

  • @Pattern 必须满足指定的正则表达式

  • @Size 集合、数组、map等的size()值必须在指定范围内

  • @Email 必须是email格式

  • @Length 长度必须在指定范围内

  • @NotBlank 字符串不能为null,字符串trim()后也不能等于“”

  • @NotEmpty 不能为null,集合、数组、map等size()不能为0;字符串trim()后可以等于“”

  • @Range 值必须在指定范围内

  • @URL 必须是一个URL

1. 依赖

  • pom.xml
       <!-- Validation校验参数     -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <!--     hutool工具包  -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.22</version>
        </dependency>

2. 普通校验

  • 我们在需要校验的Controller类上加@Validated
  • IndexController
@RestController
@Validated
@Slf4j
public class IndexController {

    @GetMapping("/test1")
    public ResponseResult<String> test1(@NotBlank(message = "用户名不能为空") String name,
                                        @NotNull(message = "用户名id不能为空") Long userId) {
        log.info("参数为:{},{}", name, userId);
        return ResponseResult.ok();
    }
}

3. 实体校验

  • 在实体中添加限制注解
@Data
@Accessors(chain = true)
public class UserVo {

    @NotBlank(message = "用户名称不能为空")
    private String name;

    @NotNull(message = "编号不能为空")
    @Max(value = 999, message = "编号需小于1000")
    @Min(value = 0, message = "编号需大于0")
    private Integer number;

    @NotNull(message = "邮箱不能为空")
    private String email;

    @Length(message = "手机号不合法")
    private String phone;
}
  • IndexController
  • 在参数实体前加@Validated
@RestController
@Validated
@Slf4j
public class IndexController {

    @GetMapping("/test1")
    public ResponseResult<String> test1(@NotBlank(message = "用户名不能为空") String name,
                                        @NotNull(message = "用户名id不能为空") Long userId) {
        log.info("参数为:{},{}", name, userId);
        return ResponseResult.ok();
    }

    @GetMapping("/test2")
    public ResponseResult<String> test2(@Validated UserVo userVo) {
        log.info("参数为:{}", JSON.toJSONString(userVo));
        return ResponseResult.ok();
    }
}

4. 异常捕获

  • 定义统一响应体
@Data
@Accessors(chain = true)
public class ResponseResult<T> implements Serializable {

    private static final long serialVersionUID = -1L;

    private Integer code;

    private String message;

    private T data;

    public ResponseResult(Integer code, String message, T data) {
        super();
        this.code = code;
        this.message = message;
        this.data = data;
    }

    private static <T> ResponseResult<T> build(Integer code, String message, T data) {
        return new ResponseResult<>(code, message, data);
    }

    public static <T> ResponseResult<T> ok() {
        return new ResponseResult<>(RespCode.OK.code, RespCode.OK.message, null);
    }

    public static <T> ResponseResult<T> ok(T data) {
        return build(RespCode.OK.code, RespCode.OK.message, data);
    }

    private static <T> ResponseResult<T> ok(String message) {
        return build(RespCode.OK.code, message, null);
    }

    public static <T> ResponseResult<T> fail() {
        return fail(RespCode.ERROR.message);
    }

    public static <T> ResponseResult<T> fail(String message) {
        return fail(RespCode.ERROR, message);
    }

    public static <T> ResponseResult<T> fail(RespCode respCode) {
        return build(respCode.code, respCode.message, null);
    }

    public static <T> ResponseResult<T> fail(RespCode respCode, String message) {
        return build(respCode.code, message, null);
    }

    public enum RespCode {
        /**
         * 业务码
         */
        OK(20000, "请求成功"),
        MY_ERROR(20433, "自定义异常"),
        UNAUTHORIZED(20401, "未授权"),
        LOGIN_FAIL(20402, "账号或密码错误"),
        ERROR(20400, "未知异常");

        RespCode(int code, String message) {
            this.code = code;
            this.message = message;
        }

        private final int code;
        private final String message;

        public int getCode() {
            return code;
        }

        public String getMessage() {
            return message;
        }
    }
}
  • 全局异常捕获
/**
 * 描述:全局统一异常处理
 *
 * @author ding
 */
@Slf4j
@RestControllerAdvice
public class ExceptionHandlerAdvice {

    /**
     * 参数验证异常
     */
    @ExceptionHandler(value = {BindException.class})
    public ResponseResult<String> handleMethodArgumentNotValidException(BindException e) {
        e.printStackTrace();
        String errorMsg = Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage();
        if (!StrUtil.isBlank(errorMsg)) {
            return ResponseResult.fail(errorMsg);
        }
        return ResponseResult.fail(e.getMessage());
    }

    /**
     * Validation参数异常
     */
    @ExceptionHandler(value = {ValidationException.class})
    public ResponseResult<String> constraintViolationException(ValidationException e) {
        e.printStackTrace();
        if (e instanceof ConstraintViolationException) {
            ConstraintViolationException err = (ConstraintViolationException) e;
            ConstraintViolation<?> constraintViolation = err.getConstraintViolations().stream().findFirst().get();
            String messageTemplate = constraintViolation.getMessageTemplate();
            if (!StrUtil.isBlank(messageTemplate)) {
                return ResponseResult.fail(messageTemplate);
            }
        }
        return ResponseResult.fail(e.getMessage());
    }

    /**
     * 异常处理
     */
    @ExceptionHandler(value = Exception.class)
    public ResponseResult<String> defaultException(Exception e) {
        e.printStackTrace();
        if (e instanceof NullPointerException) {
            return ResponseResult.fail("空指针异常");
        }
        if (e instanceof HttpRequestMethodNotSupportedException) {
            return ResponseResult.fail(e.getMessage());
        }
        return ResponseResult.fail();
    }

}

5. 实战效果

  • 访问接口test1
    在这里插入图片描述

  • 访问接口test2

6. 源码分享

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全栈小定

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值