数据校验

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

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

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");  
        }  
    }  
}

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

相关推荐
武子康28 分钟前
Java-72 深入浅出 RPC Dubbo 上手 生产者模块详解
java·spring boot·分布式·后端·rpc·dubbo·nio
椰椰椰耶2 小时前
【Spring】拦截器详解
java·后端·spring
brzhang3 小时前
我操,终于有人把 AI 大佬们 PUA 程序员的套路给讲明白了!
前端·后端·架构
wan_da_ren5 小时前
JVM监控及诊断工具-GUI篇
java·开发语言·jvm·后端
【本人】5 小时前
Django基础(一)———创建与启动
后端·python·django
lifallen6 小时前
Kafka 时间轮深度解析:如何O(1)处理定时任务
java·数据结构·分布式·后端·算法·kafka
你的人类朋友6 小时前
【✈️速通】什么是SIT,什么是UAT?
后端·单元测试·测试
程序无bug8 小时前
后端3行代码写出8个接口!
java·后端
绝无仅有8 小时前
使用LNMP一键安装包安装PHP、Nginx、Redis、Swoole、OPcache
后端·面试·github
他日若遂凌云志8 小时前
C++ 与 Lua 交互全链路解析:基于Lua5.4.8的源码剖析
后端