Springboot-参数校验相关处理

springboot项目-参数校验

通常我们在controller层接收前端传递的参数,通过springmvc进行参数绑定。但是我们无法确定参数传递的正确性,所以需要编写参数校验的代码,判断NULL,空格,是否为数字,正负,字符串长度等等,假如每个接口都编写这样的代码,会导致项目在垂直角度上存在大量冗余的代码。影响阅读和维护。
校验数据的习惯是正确的,我们无法保证每个用户都按照规定格式进行输入,有必要进行校验处理。
为了更好的关注核心的业务逻辑,减少参数校验侵入方法内部,因此有了 JRS-303 提案。

JSR是Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。

数据校验的2个工具:

  1. javax.validation.constraints
  2. Hibernate Validator
  • 区别:validation bean 是基于JSR-303标准开发出来的,使用注解方式实现,及其方便,但是这只是一个接口,没有具体实现。Hibernate Validator是一个hibernate独立的包,可以直接引用,他实现了validation bean同时有做了扩展,比较强大。Bean Validation 是一个运行时的数据验证框架,在验证之后验证的错误信息会被马上返回。

Bean Validation 2.0 中的 constraint

注解详细信息
@Null被注释的元素必须为 null
@NotNull被注释的元素必须不为 null
@AssertTrue被注释的元素必须为 true
@AssertFalse被注释的元素必须为 false
@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Negative被注释的元素必须是一个严格的负数,举例,0 被视为无效值,因为不是负数
@NegativeOrZero被注释的元素必须是一个严格的负数或者 0
@Positive被注释的元素必须是一个严格的正数,举例,0 被视为无效值,因为不是正数
@PositiveOrZero被注释的元素必须是一个严格的正数或者 0
@Size(max, min)被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction)被注释的元素必须是一个带小数的数,integer 为整数位最大值,fraction 为小数位最大值
@Past被注释的元素必须是一个过去的日期
@PastOrPresent被注释的元素必须是一个过去的日期或者现在日期
@Future被注释的元素必须是一个将来的日期
@FutureOrPresent被注释的元素必须是一个将来的日期或者现在日期
@Pattern(value)被注释的元素必须符合指定的正则表达式
@NotEmpty被注释的元素必须不为 null 或者不为空,可校验字符、集合、Map
@NotBlank被注释的元素必须不为空字符串
@Email被注释的元素必须是电子邮箱地址

Hibernate Validator 附加的 constraint

注解详细信息
@Length被注释的字符串的大小必须在指定的范围内
@Range被注释的元素必须在合适的范围内

简单的使用案例:

@Data
public class UserRegisterForm {

    @NotNull
    private String username;

    @NotBlank
    private String password;

    @Email(message = "使用正确的email")
    private String email;
}

如果前端传递的数据没有按照规定的格式要求,在参数校验时会抛出异常。通过message以制定错误消息。
通过使用@Valid注解让校验注解生效。

 @PostMapping("/register")
    public ResponseVo registerUser(@Valid @RequestBody UserRegisterForm userRegisterForm) {
        log.info("用户注册:[{}]", userRegisterForm.getUsername());
        User user = new User();
        BeanUtils.copyProperties(userRegisterForm, user);
        return userService.register(user);
    }

测试:

在这里插入图片描述

  • 结果
{
    "timestamp": "2020-12-13T06:55:36.651+0000",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "NotBlank.userRegisterForm.password",
                "NotBlank.password",
                "NotBlank.java.lang.String",
                "NotBlank"
            ],
            "arguments": [
                {
                    "codes": [
                        "userRegisterForm.password",
                        "password"
                    ],
                    "arguments": null,
                    "defaultMessage": "password",
                    "code": "password"
                }
            ],
            "defaultMessage": "不能为空",
            "objectName": "userRegisterForm",
            "field": "password",
            "rejectedValue": " ",
            "bindingFailure": false,
            "code": "NotBlank"
        },
        {
            "codes": [
                "Email.userRegisterForm.email",
                "Email.email",
                "Email.java.lang.String",
                "Email"
            ],
            "arguments": [
                {
                    "codes": [
                        "userRegisterForm.email",
                        "email"
                    ],
                    "arguments": null,
                    "defaultMessage": "email",
                    "code": "email"
                },
                [],
                {
                    "arguments": null,
                    "defaultMessage": ".*",
                    "codes": [
                        ".*"
                    ]
                }
            ],
            "defaultMessage": "请使用正确的email",
            "objectName": "userRegisterForm",
            "field": "email",
            "rejectedValue": "1111111.com",
            "bindingFailure": false,
            "code": "Email"
        }
    ],
    "message": "Validation failed for object='userRegisterForm'. Error count: 2",
    "path": "/user/register"
}
  • 快捷使用:直接在接受的参数上使用检验的注解,但是要注意必须使用@Validated 注解来使其生效
@Slf4j
@Validated // 使用 spring 的 Validated 注解标注此 Controller 是需要执行校验的,
@RestController
@RequestMapping("/demo-1")
public class Demo1Controller {
    @GetMapping("/query-1")
    public HttpStatus query1(@NotBlank(message = "不能为空") String name) {
        log.info("name is {}", name);
        return HttpStatus.OK;
    }
}

异常捕获

通常使用了参数校验后,可以看到返回的异常信息比较多,我们可以通过全局异常处理来处理,提炼出重要的错误信息返回给前端。
MethodArgumentNotValidException类:为参数异常的主要类,通过捕获该类,提取BindingResult类来得到相关的信息。

参考代码如下:

@RestControllerAdvice
@Slf4j
public class RuntimeExceptionHandler {
    /**
     * 参数校验异常进行统一异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    public ResponseVo notValidExceptionHandler(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        log.warn("参数:【{}】异常:【{}】", bindingResult.getFieldError().getField(),
                bindingResult.getFieldError().getDefaultMessage());
        return ResponseVo.error(ResponseEnum.PARAM_ERROR, bindingResult);
    }
  }

结果类:

@Data
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public class ResponseVo<T> {

    private Integer status;

    private String msg;

    private T data;

    public ResponseVo(Integer status, String msg) {
        this.status = status;
        this.msg = msg;
    }

    public ResponseVo(Integer status, T data) {
        this.status = status;
        this.data = data;
    }
    
    public static <T> ResponseVo<T> error(ResponseEnum responseEnum, BindingResult bindingResult) {
        return new ResponseVo(responseEnum.getCode(),
                Objects.requireNonNull(bindingResult.getFieldError()).getField()
                        + " " + bindingResult.getFieldError().getDefaultMessage());
    }
}

以上为通常使用的方式,更多操作类似:分组校验,层级校验的使用可以查看该文章

参考:
Bean Validation 校验实践
SpringBoot使用Validation校验参数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值