数据校验

在日常开发中,我们有时候需要对一些参数进行校验,此时需要书写大量的逻辑判断,会显得代码比较冗余(如图所示)。

此时可以使用如下注解方式来简化代码。

Valid注解方式

引入相关依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    <version>3.2.1</version>
</dependency>
java 复制代码
@Data
public class ModifyNameReq {
    @NotBlank
    @Size(max = 6,message = "名称不能太长哦!")
    private String name;
    @NotBlank
    @Size(max = 6,message = "名称不能太长哦!")
    private String address;
    @NotBlank
    private String img;
}

@Valid要加上,否则会没有效果,校验不了

java 复制代码
@RestController
public class EurekaServerController {
    @PostMapping("test")
    public String save(@Valid @RequestBody ModifyNameReq nameReq){
        return "OK";
    }
}

使用postman进行测试

此时如果不配置异常处理器,会出现如下错误。所以为了更好的显示和更友好的提醒用户可以配置异常处理器。

异常处理器

java 复制代码
@RestControllerAdvice  // 监听打了@RestController注解的Controller
public class GlobalExceptionHandler {
    /**
     * validation参数校验异常
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class) // 监听该类型的错误
    public ApiResult<?> methodArgumentNotValidException(MethodArgumentNotValidException exception){
        StringBuilder errorMsg = new StringBuilder();
        exception.getBindingResult().getFieldErrors() // 获取所有错误字段信息
                .forEach(item->errorMsg.append(item.getField()).append(item.getDefaultMessage()));
        return ApiResult.fail(CommonErrorEnum.PARAM_VALID.getCode(),errorMsg.substring(0,errorMsg.length() -1));
    }
}

上述代码中,大家只需要了解如何获取错误字段信息即可,前面的ApiResult只是用来封装返回给前端结果的工具类

此时有的小伙伴就又会说了,那我如果是对象里面包含了一个对象,也需要进行数据的校验怎么办呢?此时我们就可以采取下面的方式了。

java 复制代码
@Data
public class ModifyNameReq {
    @NotBlank
    @Size(max = 6,message = "名称不能太长哦!")
    private String name;
    @NotBlank
    private String img;
    @Valid // 这个注解会触发Address对象的校验  
    private Address address;
}
java 复制代码
@Data
public class Address {
    @NotBlank(message = "城市不能为空")
    @Size(max = 50, message = "城市名称不能超过50个字符")
    private String city;  
      
    @NotBlank(message = "街道不能为空")  
    @Size(max = 100, message = "街道名称不能超过100个字符")  
    private String street;  
}

此时我们并没有输入street字段,此时看看会出现什么错误呢?

大家可以很清晰地看见我们的嵌套的校验生效了。

此时又有小伙伴们说了,那么如果对象里面包含一个集合对象呢

java 复制代码
@Data
public class ModifyNameReq {
    @NotBlank
    @Size(max = 6,message = "名称不能太长哦!")
    private String name;
    @NotBlank
    private String img;
    @Valid // 这个注解会触发Address对象的校验  
    private List<Address> address;
}

此时发送请求,出现的异常会跟上述异常相同。

非注解方式

在上面的示例中,ModifyNameReq类包含了一个Address类型的属性和一个Address类型的列表属性。对于这两个属性,我们都使用了@Valid注解来指示需要对它们进行校验。此外,我们还为citystreetname等属性添加了其他的校验注解,如@NotNull@Size

要使用这些校验注解,还需要配置一个校验器(Validator),并在需要的时候调用它来执行校验。这通常是通过Spring框架自动完成的,但是也可以手动创建和使用Validator实例。以下是一个简单的示例,展示了如何手动使用Validator来校验ModifyNameReq对象:

java 复制代码
import javax.validation.ConstraintViolation;
import javax.validation.Validation;  
import javax.validation.Validator;  
import javax.validation.ValidatorFactory;
public class ValidationExample {  
  
    public static void main(String[] args) {  
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();  
        Validator validator = factory.getValidator();

        ModifyNameReq modifyNameReq = new ModifyNameReq();
        modifyNameReq.setImg("http:132.png");
        modifyNameReq.setName("手动创建使用Validator实例");
        Address address = new Address();
        address.setCity("北京");
        modifyNameReq.setAddress(Arrays.asList(address));
        Set<ConstraintViolation<ModifyNameReq>> violations = validator.validate(modifyNameReq);
        if (!violations.isEmpty()) {  
            for (ConstraintViolation<ModifyNameReq> violation : violations) {
                System.out.println(violation.getMessage());  
            }  
        } else {  
            System.out.println("Validation succeeded");  
        }  
    }  
}

此时大家可以运行这段代码,看看会有什么信息打印出来吧。

相关推荐
涡能增压发动积8 小时前
同样的代码循环 10次正常 循环 100次就抛异常?自定义 Comparator 的 bug 让我丢尽颜面
后端
Wenweno0o8 小时前
0基础Go语言Eino框架智能体实战-chatModel
开发语言·后端·golang
swg3213218 小时前
Spring Boot 3.X Oauth2 认证服务与资源服务
java·spring boot·后端
tyung8 小时前
一个 main.go 搞定协作白板:你画一笔,全世界都看见
后端·go
gelald8 小时前
SpringBoot - 自动配置原理
java·spring boot·后端
殷紫川9 小时前
深入拆解 Java 内存模型:从原子性、可见性到有序性,彻底搞懂 happen-before 规则
java·后端
元宝骑士9 小时前
FIND_IN_SET使用指南:场景、优缺点与MySQL优化策略
后端·mysql
用户31952370347719 小时前
记一次 PostgreSQL WAL 日志撑爆磁盘的排查
后端
nghxni9 小时前
LightESB PlatformHttp v3.0.0:JSONPath 订单转换 HTTP 路由实战
后端
武子康10 小时前
大数据-263 实时数仓-Canal 增量订阅与消费原理:MySQL Binlog 数据同步实践
大数据·hadoop·后端