该文章涉及到了嵌套校验(Nested Validation)的细节。虽然这两种写法看起来接近,但它们在功能上存在关键性的区别,尤其是在集合元素是否被校验上。


🔍 两种写法对比

✅ 写法一(推荐):

@NotEmpty(message = "不能为空")
private List<@Valid FileDTO> deviceSnFiles;

⚠️ 写法二:

@Valid
@NotEmpty(message = "不能为空")
private List<FileDTO> deviceSnFiles;

✅ 核心区别

写法 是否校验 List 本身非空 是否递归校验 List 中的每个 FileDTO 说明
@Valid + @NotEmpty(字段上) ✅ 是 ❌ 否 只对 List 本身做非空检查,不递归校验元素
@NotEmpty(字段)+ @Valid(元素) ✅ 是 ✅ 是 推荐写法,既校验集合不为空,也校验每个元素是否合法

✳️ 为什么写法二不校验元素?

因为 @Valid 作用于字段本身时,只告诉校验器:“这个字段是个对象,需要校验它的内部字段”。

但当字段是 List<FileDTO>,你需要告诉校验器去递归校验里面的每一个元素,这必须加在泛型参数上:List<@Valid FileDTO>

如果你写的是 @Valid List<FileDTO>,不会自动深入 List 的每个元素,除非你用 JSR-380(Bean Validation 2.0)并配置了深度级别,但仍不是标准推荐。


🧪 举个例子:

@Data
public class FileDTO {
    @NotBlank(message = "文件名不能为空")
    private String name;
}

对比验证效果:

写法一 ✅
@NotEmpty(message = "不能为空")
private List<@Valid FileDTO> deviceSnFiles;

如果传入:

{
  "deviceSnFiles": [
    { "name": "" }
  ]
}

会触发校验错误:“deviceSnFiles[0].name 不能为空”


写法二 ⚠️
@Valid
@NotEmpty(message = "不能为空")
private List<FileDTO> deviceSnFiles;

同样的 JSON,只会验证 List 不为空,不会校验 name 字段是否为空。


✅ 最终结论

问题 回答
两个写法作用一样吗? ❌ 不一样
哪个写法更规范? @NotEmpty List<@Valid FileDTO> 更规范
如果想校验 List 非空且校验每个元素 ✅ 必须把 @Valid 放在元素上(即泛型参数上)

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐