SpringBoot中集成参数校验Validation

为了提供可靠的API接口,对参数进行校验,保证数据入库的正确性,同事通过添加注释使用Validation规范避免写一大堆的if -else的校验语句。使代码更加简单清晰。

1、注解

1.1 空和非空校验

  • @NotBlank:只能用于校验字符串不能为null,并且字符串 #trim() 以后 length 要大于 0 。
  • @NotEmpty:集合对象的元素不为 0 ,即集合不为空,也可以用于字符串不为 null 。
  • @NotNull:不能为 null 。
  • @Null:必须为 null 。

1.2 数值校验

  • @DecimalMax(value) :被注释的元素必须是一个数字,其值必须小于等于指定的最大值。

  • @DecimalMin(value) :被注释的元素必须是一个数字,其值必须大于等于指定的最小值。

  • @Digits(integer, fraction) :被注释的元素必须是一个数字,其值必须在可接受的范围内。

  • @Positive :判断正数。

  • @PositiveOrZero :判断正数或 0 。

  • @Max(value) :该字段的值只能小于或等于该值。

  • @Min(value) :该字段的值只能大于或等于该值。- @Negative :判断负数。

  • @NegativeOrZero :判断负数或 0 。

1.3 Boolean 值检查

  • @AssertFalse :被注释的元素必须为 true 。

  • @AssertTrue :被注释的元素必须为 false 。

1.4 长度检查

  • @Size(max, min) :检查该字段的 size 是否在 min 和 max 之间,可以是字符串、数组、集合、Map 等。

1.5 日期检查

  • @Future :被注释的元素必须是一个将来的日期。

  • @FutureOrPresent :判断日期是否是将来或现在日期。

  • @Past :检查该字段的日期是在过去。

  • @PastOrPresent :判断日期是否是过去或现在日期。

1.6 其它检查

  • @Email :被注释的元素必须是电子邮箱地址。

  • @Pattern(value) :被注释的元素必须符合指定的正则表达式。

2、@Valid和@Validated区别

@Valid注解,是Bean Validation所定义,支持嵌套校验。可以添加到方法参数,普通方法,成员变量,构造方法上。

@Validated注解,是Spring Validation所定义,可以添加到类,方法参数,普通方法上。同时@Validated有value属性,支持分组校验。

3、快速入门,引入依赖


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

因为 spring-boot-starter-validation 已经引入了 hibernate-validator所以无需重复引入hibernate-validator依赖。

4、创建基本的实体类

4.1 UserVo实体类

package com.lingyi.mybatis.vo;

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import org.hibernate.validator.constraints.Length;

import javax.crypto.Mac;

@Data
public class UserVo {
    @NotEmpty(message = "登录账号不能为空")
    @Length(min = 5,max = 16 ,message = "账号长度为5-16位")
    @Pattern(regexp = "^[A-Za-z0-9]+$" ,message = "账号格式为数字和字母")
    private String username;

    @NotEmpty(message = "密码不能为空")
    @Length(min = 4,max = 16,message = "密码为4-16位")
    private String password;
}

4.2 LoginCotroller上编写接口,在类上添加@Validated注解,表示LoginCotroller上所有的的接口都需要进行参数校验。

import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/login")
@Validated
public class LoginController {

    private Logger logger = LoggerFactory.getLogger(getClass());
    @PostMapping
    public  UserVo login(@RequestBody @Validated UserVo userVo){ //在接口参数上使用@Valid和@Validated都可以;
        logger.info("登录 login {}",userVo);
        return userVo;
    }

    @GetMapping("/get")
    public UserVo get(@RequestParam("id") @Min(value = 0L,message = "编号必须大于0") Integer id){
        logger.info("get id = {}",id);
        UserVo userVo = new UserVo();
        userVo.setPassword("1234567");
        userVo.setUsername("张三");
        return  userVo;

    }
}

4.3 启动程序,测试

启动程序后,在浏览器中输入swagger访问地址:http://127.0.0.1:8081/swagger-ui.html 测试对应的接口。通过查看返回结果,果然对对应的字段进行了校验。

SpringBoot中集成参数校验Validation_第1张图片

后台报错:

测试get接口,输入参数id为-1,查看返回结果:

SpringBoot中集成参数校验Validation_第2张图片

5、添加全局异常处理类

通过返回的错误信息看到,Validator校验框架返回的错误提示不友好,为了返回更加友好的错误提示,可以通过添加全局异常处理类GlobalExcetionHandler.java

在包com.lingyi.mybatis.exception下创建全局异常处理类GlobalExcetionHandler.java

import jakarta.validation.ConstraintViolationException;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.List;
import java.util.stream.Collectors;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ErrorResponse handleValidationException(MethodArgumentNotValidException ex) {
        BindingResult result = ex.getBindingResult();
        List fieldErrors = result.getFieldErrors();
        List errors = fieldErrors.stream()
                .map(error -> error.getField() + ": " + error.getDefaultMessage())
                .collect(Collectors.toList());
        return new ErrorResponse("Validation failed", errors);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ErrorResponse handleConstraintViolationException(ConstraintViolationException ex) {
        List errors = ex.getConstraintViolations().stream()
                .map(violation -> violation.getPropertyPath() + ": " + violation.getMessage())
                .collect(Collectors.toList());
        return new ErrorResponse("Validation failed", errors);
    }

    @Data
    @AllArgsConstructor
    private static class ErrorResponse {
        private String message;
        private List errors;
    }
}

在上面的代码中,我们使用@ControllerAdvice注解来定义一个全局的异常处理类。然后我们使用@ExceptionHandler注解来定义处理MethodArgumentNotValidException和ConstraintViolationException异常的方法。在这些方法中,我们可以根据具体的异常类型来处理校验异常,并返回一个包含错误信息的ErrorResponse对象。

这样,当发生校验异常时,Spring Boot会自动调用对应的异常处理方法,并返回统一格式的错误信息给客户端。这样可以使代码更加规范和易于维护。

再次测试返回给前端的错误提示如下:

SpringBoot中集成参数校验Validation_第3张图片

你可能感兴趣的:(java,开发语言)