如何精准拿捏 @NotEmpty?这波操作让同事彻底懵了!💫

🏆本文收录于「滚雪球学SpringBoot」专栏,专业攻坚指数级提升持续更新中,up!up!up!!

📜 前言

嘿,家人们,上午好!昨晚我通宵加班,终于把大家期待已久的非空校验注解篇之 《@NotEmpty 注解如何妙用?》完整给输出啦,给自己呱唧呱唧~👋👋。在我们日常项目开发中,经常都会遇到用户输入各种数据。如果数据不合法(比如空字符串、空列表等),那真的是让人头疼!尤其是在处理关联信息时,得层层校验是否为 null 等。更麻烦的是,有些字段必须有值才合理,比如用户名、订单列表、地址信息等,空了就无效,脏数据也搅乱届时数据挖掘等价值。这时,@NotEmpty 就能派上大用场了!

@NotEmpty它是一个非常实用的校验注解,用来确保字符串或集合不为空(与 @NotNull 不同的是,它不仅要求不为 null,还要求字段有实际内容)。所以,如果你心里存有疑惑,别急,今天我们就来详细的学习或者回顾 @NotEmpty 注解的使用方法。我还会结合一些实例和进阶用法,争取给大家讲解得清清楚楚,明明白白🎉。你准备好了没?我即将要开始咯。

📚 目录

  1. 🧐 什么是 @NotEmpty?它的作用是什么?
  2. 🎩 @NotEmpty 的基础用法
  3. ✍️ 实战演示:用 @NotEmpty 校验必填字段
  4. 🔄 进阶技巧:@NotEmpty 与其他校验注解的组合使用
  5. 🛠️ 深入分析:@NotEmpty 的实现原理
  6. 💡 最佳实践与常见误区
  7. 📈 总结与心得

🧐 什么是 @NotEmpty?它的作用是什么?

所谓 @NotEmpty ,它是 Java Bean Validation 提供的一个注解,主要用于校验集合类型或字符串是否为空。和 @NotNull 不同,@NotEmpty 既要求字段不为 null,还要求其中必须有内容。这意味着,对于字符串,@NotEmpty 要求字符串不为 "";对于集合(如 ListSet),要求集合不为空。

通俗点说,@NotEmpty 可以确保字段不只是存在而已,还要有"实打实"的内容。这个注解特别适用于必填字段,如用户名、订单项等,避免在应用中接收到空数据导致的错误处理。💡

@NotEmpty 属于 javax.validation.constraints类包目录下,这是 Java Bean Validation(JSR 380)的一部分,具体实现通常由 Hibernate Validator 提供支持。具体可见如下源码截图:

感兴趣的小伙伴可深入进行钻研摸索。

🎩 @NotEmpty 的基础用法

既然讲解了它的原理及作用,现在大家肯定都想了解它是如何使用的?确实!我主打的就是理论+实操;说实话,使用 @NotEmpty 非常简单,只需在字段上加上这个注解即可,与@NotNull、@NotBlank等注解用法一致。@NotEmpty 默认会触发校验逻辑,检测该字段是否为空或为空集合。以下是几个常见的应用场景:

  1. 校验字符串不为空
  2. 校验集合不为空
  3. 校验数组不为空

基础使用示例代码:

假设我们现在有一个简单的用户类 User,包含 usernameroles 字段。我们希望 username 必须有值,且用户角色列表 roles 不能为空,那满足这个需要的, @NotEmpty 注解的作用就可以实现这两个字段的校验:

示例代码如下:

java 复制代码
import javax.validation.constraints.NotEmpty;
import java.util.List;

public class User {

    @NotEmpty(message = "用户名不能为空")
    private String username;

    @NotEmpty(message = "用户角色列表不能为空")
    private List<String> roles;

    // Getter 和 Setter
}

在我如上这个例子中,如果 username 字段为空字符串或 roles 为空列表,校验将不会通过,并返回我们自定义的提示信息,这个不妨大家可在本地测验一波。

✍️ 实战演示:用 @NotEmpty 校验必填字段

为了让大家更直观地理解 @NotEmpty 的用法,我们来一个真切实际的案例。在这个例子中,我们创建一个用户新增的接口,要求 nameemail 等字段信息在新增时不能为空,用户角色列表也必须有内容,如下是实现步骤,请看:

Step 1: 引入依赖

在项目的 pom.xml 文件中引入 spring-boot-starter-validation 依赖,启用校验功能。

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Step 2: 定义用户类并使用 @NotEmpty 注解

定义一个实体类,且定义好映射字段及需要被校验的字段和提示信息,例如用户名不能为空...这里大家可参考如下,着重通过 @NotEmpty 注解来实操。

java 复制代码
import javax.validation.constraints.NotEmpty;
import java.util.List;

public class User {

    @NotEmpty(message = "用户名不能为空")
    private String name;

    @NotEmpty(message = "邮箱不能为空")
    private String email;
    
    @Positive(message = "年龄必须为正数")
    private Integer age;

    @NotEmpty(message = "用户角色列表不能为空")
    private List<String> roles;

    // Getter 和 Setter
}

Step 3: 创建用户控制器并启用校验

在控制器中定义用户新增接口,并在方法参数中添加 @Validated 注解,启用 @NotEmpty 的校验功能。示例代码如下:

java 复制代码
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;

import javax.validation.Valid;

@RestController
@RequestMapping("/system/testUser")
public class UserController {
    /**
     * 新增user
     */
    @ApiOperation("新增user")
    @PostMapping("/add")
    public R<Void> add(@Validated @RequestBody User user) {
        return toR(userService.insert(user));
    }
}

Step 4: 测试接口

写好接口之后,重启项目,这时我们便可以通过 Postman 或其他工具模拟发送请求,如果 nameemailroles 字段为空,将会收到相应的校验错误提示,比如"用户名不能为空"或"用户角色列表不能为空"等,大家可在本地随意模拟访问试试。🎉

模拟场景1:用户名直接传空串

这里我们请求的时候,将name直接传空串进行请求。Postman请求如下:

如上成功验证若用户名传入空串则自动会被拦截,且提示对应的message信息,如"姓名不能为空",拦截成功!

模拟场景2:邮箱号直接传null值

继续模拟,这里我们在发请求的时候,将email直接传null值。Postman请求如下:

如上成功验证邮箱号传null值依然会被拦截,强行提醒"邮箱不能为空",告知用户其字段信息的校验规则,拦截成功!

模拟场景3:年龄直接传负值

继续模拟,这里我们在发请求的时候,将age直接传个负数。Postman请求如下:

如上成功验证年龄传负值也依然会被拦截,强行被提示"年龄必须为正数"。

如上成功验证年龄传负值被拦截没有进请求业务中,强行提醒"年龄必须为正数",告知用户其字段信息的校验规则,拦截成功!

模拟场景4:用户角色列表直接null值

这里我们模拟一下,在发请求的时候,将用户角色列表直接传个null值试试。Postman请求如下:   如上成功验证用户角色列表为null时被拦截住了,强行提醒"用户角色列表不能为空",告知用户其字段信息的校验规则,拦截成功!

模拟场景5:正常值传入

正常将对应的值进行传入,我们可以debug验证一下,是否可获取到各类字段值。

根据如上截图,很明显是成功进入到了新增业务逻辑中,所有的字段内容都通过了校验,符合我们定义的校验规则。总之,这里都已经替大家都测试过了,大家可放心"食用",根据不同的场景选择恰当的校验注解。

🔄 进阶技巧:`@NotEmpty` 与其他校验注解的组合使用

在某些场景下,@NotEmpty 也可以和其他注解组合使用,实现更精确的数据校验需求。

1. 与 @Size 组合

如果我们不仅希望字段非空,还希望字符串的长度符合特定要求,可以组合使用 @NotEmpty@Size。例如,限制用户名不为空且长度在 3 到 15 个字符之间:

示例代码

java 复制代码
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;

public class User {

    @NotEmpty(message = "用户名不能为空")
    @Size(min = 3, max = 15, message = "用户名长度必须在3到15个字符之间")
    private String name;

    // 其他字段和方法
}

示例代码解析

在本次的代码演示中,我将会深入剖析每句代码,详细阐述其背后的设计思想和实现逻辑。通过这样的讲解方式,我希望能够引导同学们逐步构建起对代码的深刻理解。我会先从代码的结构开始,逐步拆解每个模块的功能和作用,并指出关键的代码段,并解释它们是如何协同运行的。通过这样的讲解和实践相结合的方式,我相信每位同学都能够对代码有更深入的理解,并能够早日将其掌握,应用到自己的学习和工作中。

如上这段代码定义了一个 User 类,其中 name 字段使用了 @NotEmpty@Size 注解进行校验,确保数据的有效性和规范性。

  1. @NotEmpty(message = "用户名不能为空")

    • 功能 : 检查 name 字段是否为 null 或空字符串。
    • 场景 :
      • 如果 name 字段为 null 或空字符串(例如 """ "),则校验不通过,返回错误信息 "用户名不能为空"
    • 目的: 确保用户必须输入用户名,字段不能是空的。
  2. @Size(min = 3, max = 15, message = "用户名长度必须在3到15个字符之间")

    • 功能 : 校验 name 字段的长度是否在指定范围内。
    • 规则 :
      • min = 3: 用户名至少包含 3 个字符。
      • max = 15: 用户名最多包含 15 个字符。
    • 场景 :
      • 如果 name 的长度小于 3 或大于 15,校验不通过,并返回错误信息 "用户名长度必须在3到15个字符之间"
    • 目的: 确保用户名的长度符合业务需求。
  3. 结合使用

    • 校验顺序:先通过 @NotEmpty 校验非空,如果校验通过,再进行 @Size 的长度范围校验。
    • 确保 name 字段既不为空,又符合长度限制。

使用场景:

该代码适用于需要对用户输入的用户名进行基础校验的场景,例如注册页面或表单数据提交。这样可以避免用户名为空或者长度不合法,提高数据的准确性和业务逻辑的健壮性。

示例输入与校验结果:

输入值 校验结果 错误信息
null 不通过 用户名不能为空
"" 不通过 用户名不能为空
"ab" 不通过 用户名长度必须在3到15个字符之间
"abcdef" 通过
"abcdefghijklmnop" 不通过 用户名长度必须在3到15个字符之间

本地运行展示

本地实际测试结果展示如下:

通过如上组合使用,既可以控制name为空检验,还能校验其值的字符串长度。

2. 与 @Pattern 组合

在校验字符串格式时,可以将 @NotEmpty@Pattern 结合使用。例如,要求用户的邮箱不为空且符合邮箱格式:

示例代码

java 复制代码
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;

public class User {

    @NotEmpty(message = "邮箱不能为空")
    @Pattern(regexp = "^[\\w-\\.]+@[\\w-]+\\.[\\w-]{2,4}$", message = "邮箱格式不正确")
    private String email;

    // 其他字段和方法
}

通过这些组合,我们可以实现更精细化的校验规则,确保数据符合业务需求。

示例代码解析

如上这段代码我展示了一个 User 类中的 email 字段的校验规则,使用了两个注解 @NotEmpty@Pattern,用于进行数据校验。

  1. @NotEmpty(message = "邮箱不能为空")

    • 功能 : 检查 email 字段是否为空或仅包含空白字符。
    • 场景 : 如果 email 字段为 null 或者是空字符串(例如 """ "),会抛出一个校验错误,并显示错误消息 "邮箱不能为空"
    • 作用: 确保用户填写了邮箱字段。
  2. @Pattern(regexp = "^[\\w-\\.]+@[\\w-]+\\.[\\w-]{2,4}$", message = "邮箱格式不正确")

    • 功能 : 校验 email 字段的格式是否符合邮箱的正则表达式规则。
      • ^[\\w-\\.]+: 匹配邮箱用户名部分(由字母、数字、下划线、连字符、点组成)。
      • @[\\w-]+: 匹配邮箱的域名部分(如 gmail)。
      • \\.[\\w-]{2,4}$: 匹配顶级域名(如 .com.org 等)。
    • 场景 : 如果用户输入的邮箱格式不正确(例如缺少 @.com),会抛出校验错误,并显示 "邮箱格式不正确"
  3. 结合使用

    • 先通过 @NotEmpty 校验是否为空。
    • 再通过 @Pattern 校验格式是否正确。
    • 校验顺序 : 先校验 @NotEmpty,如果为空直接抛出错误,不再进行格式校验。

本地运行展示

这段代码用于对用户的邮箱输入进行基础校验,保证提交的数据既有内容又符合标准邮箱格式,可以防止非法输入,提高系统的可靠性和数据质量。

本地实际测试结果展示如下:


🛠️ 深入分析:@NotEmpty 的实现原理

@NotEmpty注解,它 是 Bean Validation(JSR 380)标准中的一个注解,用于对字符串、集合、数组等类型进行非空校验。在校验机制中,@NotEmpty 依赖于 Bean Validation 提供的约束校验器 NotEmptyValidator,该校验器会检查字段是否为空,字符串是否为 "" 或集合是否为空集合。

在 Spring Boot 中,Bean Validation 默认启用,结合 @Valid 注解可以方便地触发校验机制,使得数据校验简单快捷。由于 Bean Validation 是标准化的校验框架,因此 @NotEmpty 可以在大多数 Java 框架中无缝使用,不仅限于 Spring。

💡 最佳实践与常见误区

  1. 合理选择校验注解@NotEmpty@NotNull@NotBlank 有所不同,@NotEmpty 适用于集合或字符串等需要不为空的场景,而 @NotBlank 更适合用于仅验证字符串内容不为空白。
  2. 组合使用 :在有多重校验需求时,可以将 @NotEmpty 与其他注解组合使用,比如 @Size@Pattern 等。
  3. 清晰的错误信息 :使用 message 属性提供清晰的错误提示,方便用户理解错误原因。
  4. 注意使用范围@NotEmpty 适用于字符串、集合、数组等,无法用于校验整数类型。对于整型字段的校验应选择其他注解,如 @Min@Max
  5. 保证前端数据校验:虽然后端校验很重要,但也建议在前端进行必要的非空验证,提升用户体验。

📈 总结与心得

@NotEmpty 注解,它是一个非常实用的校验注解,帮助我们在后端实现接口轻松实现字段的非空校验,确保数据的完整性和有效性。再通过结合其他注解,@NotEmpty 能实现更加精细的校验逻辑,避免冗余代码的编写。希望通过这篇文章,你能够更加深入地理解 @NotEmpty 的用法,并在实际项目中灵活应用它!

如果你的项目中还没投入使用,赶紧试试 @NotEmpty 非空校验吧,让你的代码不仅简洁,还能提高代码阅读性,谁用谁爽系列,没有之一。

📣 关于我

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿哇。

-End-

相关推荐
devlei2 小时前
从源码泄露看AI Agent未来:深度对比Claude Code原生实现与OpenClaw开源方案
android·前端·后端
pshdhx_albert3 小时前
AI agent实现打字机效果
java·http·ai编程
沉鱼.443 小时前
第十二届题目
java·前端·算法
努力的小郑4 小时前
Canal 不难,难的是用好:从接入到治理
后端·mysql·性能优化
赫瑞4 小时前
数据结构中的排列组合 —— Java实现
java·开发语言·数据结构
Victor3564 小时前
MongoDB(87)如何使用GridFS?
后端
Victor3565 小时前
MongoDB(88)如何进行数据迁移?
后端
小红的布丁5 小时前
单线程 Redis 的高性能之道
redis·后端
GetcharZp5 小时前
Go 语言只能写后端?这款 2D 游戏引擎刷新你的认知!
后端
周末也要写八哥5 小时前
多进程和多线程的特点和区别
java·开发语言·jvm