@Valid对象嵌套List对象校验无效的解决方案

引言:
在使用Spring框架进行数据校验时,有时会遇到@Valid注解无法校验嵌套的List对象的情况。本文将介绍这个问题的原因,并提供解决方案,帮助您有效地校验嵌套的List对象。

问题背景:
Spring框架提供了基于注解的数据校验功能,其中@Valid注解用于标记需要进行校验的对象。然而,当对象中包含嵌套的List对象时,外层使用@Valid注解无法对嵌套的List对象进行校验。

原因分析:
默认情况下,Spring框架对嵌套对象的校验支持较好,但对于嵌套的List对象,@Valid注解并不会自动递归进行校验。

controller如下:

public Objects flights(@RequestBody @Valid AForm aForm){
        return null;
    }

Form如下:

public class AForm {

    @NotNull(message = "数据更新时间必选")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    private Date updateTime;

    private List<ASubForm> updateList;
}

public class ASubForm {

    @NotBlank(message = "航班号必选")
    private String FlightNumber;

    @NotBlank(message = "航班日期必选")
    private String FlightDate;

    @NotBlank(message = "离港机场必选")
    private String DepAirport;

    @NotBlank(message = "目的机场必选")
    private String ArrAirport;
}

问题:
controller调用的时候只有外层的updateTime有提示数据更新时间必填,航班号航班日期等为空都不进行校验。

解决方案:
修改AForm,在list对象上加上注解 @Valid就能正常校验了

public class AForm {

    @NotNull(message = "数据更新时间必选")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    private Date updateTime;

 	@Valid
    private List<ASubForm> updateList;
}

在使用Spring框架进行数据校验时,可以在嵌套的List对象上添加@Valid注解,以启用对嵌套对象的递归校验。这样,Spring框架会自动对List中的每个元素应用校验规则。
例如:

public class YourClass {
    @Valid
    private List<YourNestedClass> nestedList;
    // 其他属性和方法
}

通过在List对象上添加@Valid注解,Spring框架会自动递归校验嵌套对象,并将校验结果返回。

这种方式是更简便的解决方案,可以避免手动递归校验或自定义注解和校验器。建议优先考虑在嵌套的List对象上使用@Valid注解来实现校验。

除了使用@Valid注解,还有其他方法可以对嵌套的List对象进行校验。以下是一些备选方案:

  1. 使用自定义校验器:
    您可以编写自定义的校验器来处理嵌套的List对象。自定义校验器可以实现对List中每个元素的校验逻辑,并进行递归校验。

首先,创建一个自定义的校验器类:

public class ListValidator implements ConstraintValidator<ValidList, List<?>> {
    @Override
    public void initialize(ValidList constraintAnnotation) {
    }

    @Override
    public boolean isValid(List<?> list, ConstraintValidatorContext context) {
        if (list == null || list.isEmpty()) {
            return true; // 空列表不进行校验
        }

        // 执行自定义的校验逻辑
        for (Object element : list) {
            // 校验每个元素
            // ...
        }

        return true; // 校验通过
    }
}

然后,创建一个自定义的注解来应用该校验器:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ListValidator.class)
public @interface ValidList {
    String message() default "Invalid list";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

最后,在需要进行嵌套List对象校验的地方使用该注解:

public class YourClass {
    @ValidList
    private List<YourNestedClass> nestedList;
    // 其他属性和方法
}

通过自定义校验器和注解,您可以实现对嵌套的List对象的校验逻辑。

  1. 手动递归校验:
    另一种方法是手动递归校验嵌套的List对象。您可以在校验对象的方法中,手动对List对象的每个元素应用校验规则。
public class YourClass {
    private List<@Valid YourNestedClass> nestedList;
    // 其他属性和方法

    public void validate() {
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        Validator validator = validatorFactory.getValidator();
        for (YourNestedClass element : nestedList) {
            Set<ConstraintViolation<YourNestedClass>> violations = validator.validate(element);
            // 处理校验错误
        }
    }
}

通过手动递归校验List对象的每个元素,您可以实现对嵌套的List对象的校验。

这些是一些可选的方法,可用于对嵌套的List对象进行校验。您可以根据具体需求和情况选择适合您的解决方案。

请注意,以上方法也可以与@Valid注解结合使用,以实现更全面的校验。

你可能感兴趣的:(程序员的日常,java,servlet,spring)