🏆本文收录于「滚雪球学SpringBoot」专栏,专业攻坚指数级提升持续更新中,up!up!up!!
📜 前言
嘿,家人们!前两期我专门为同事写了两篇关于非空校验的文章,结果她特别客气,直接表示要请我吃饭感谢我。你们说,这顿饭我是去还是不去呢?要是我去了,这篇文章就没法写了;但如果这篇文章发出来了,那就说明我没去……哈哈!不过,话说回来,如果你也常常在表单数据校验中搞不清 @NotNull
和 @NotBlank
的区别,那么这篇文章绝对是为你量身打造的!
😄 在数据校验中,非空检查是第一步,保证输入数据的完整性是开发的基本要求。然而,@NotNull
和 @NotBlank
这两个“非空守护者”看起来非常相似,实则各有千秋。如果用错了,很可能会引发一些意想不到的校验问题,就像我那同事上期制造的“生产事故”一样,险些让人怀疑人生!
好了,废话不多说,本期内容正式开启!我将深入解析这两个注解的用法、适用场景以及底层实现的差异。除此之外,我还准备了一些小实例,助你快速掌握它们的核心区别,轻松避免踩坑!💪准备好了吗?我要开始咯。
📚 目录
- 🧐 @NotNull 与 @NotBlank 的基础概念
- 🎩 使用场景与适用类型
- ✍️ 实例演示:@NotNull 和 @NotBlank 在代码中的实际应用
- 🤔 它们与 @NotEmpty 有什么不同?
- 🛠️ 深度解析:底层原理与实现区别
- 💡 最佳实践与常见误区
- 📈 总结与心得
🧐 @NotNull 与 @NotBlank 的基础概念
在数据验证中,@NotNull
和 @NotBlank
都是用于保证字段的非空性,但二者的非空性定义却有所不同:
-
@NotNull
:要求字段不能是null
。换句话说,如果一个字段被@NotNull
标注,那么这个字段在使用时必须存在值,但是允许它是空字符串或空集合(所以说在某些场景下,需要特别注意其区别用法,用错了可就罪过了)。 -
@NotBlank
:要求字段不仅不能是null
,还不能是空字符串,且内容不能全为空格。这意味着,@NotBlank
是一个更严格的验证注解,通常用于字符串类型字段。
简单来说,@NotNull
注解只是保证字段存在,而 @NotBlank
还会进一步确保字段内容有意义。
🎩 使用场景与适用类型
虽然 @NotNull
和 @NotBlank
都用于非空检查,但它们的应用场景和适用类型却有明显的区别:
-
@NotNull
适用于任何对象类型,可以用于String
、List
、Map
、Integer
等,甚至自定义类的字段。例如,在用户实体类中,如果我们希望userId
、username
等字段不能为null
,可以用@NotNull
来标注。 -
@NotBlank
只适用于String
类型,因为它的检查内容包括非空白字符。@NotBlank
用于确保用户输入的字符串不为空且有实际内容,适合像用户名、密码、电子邮件这类字段。
举例对比
假设我们有一个 User
类,需要确保用户名、邮箱不为空,年龄可以为空,但如果填写则必须有实际内容,示例代码如下:
import javax.validation.constraints.NotNull;
import javax.validation.constraints.NotBlank;
public class User {
@NotNull(message = "用户ID不能为空")
private Integer userId;
@NotBlank(message = "用户名不能为空")
private String username;
@NotNull(message = "年龄不能为空")
private Integer age;
// Getter 和 Setter
}
在这个例子中,userId
和 age
使用 @NotNull
进行校验检查,而 username
则用 @NotBlank
确保用户输入实际内容。
✍️ 实例演示:@NotNull 和 @NotBlank 在代码中的实际应用
接下来我们通过一个简单的示例代码,展示 @NotNull
和 @NotBlank
的实际应用效果。
Step 1: 导入对应依赖
首先,为了使用 @NotNull
,你需要在项目中引入一个支持 Jakarta Bean Validation 的实现库,比如 Hibernate Validator。
以下是常见的 Maven 依赖配置:
Maven 配置:
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.2.5.Final</version> <!-- 请根据需要选择版本 -->
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
Gradle 配置:
implementation 'org.hibernate.validator:hibernate-validator:6.2.5.Final'
implementation 'javax.validation:validation-api:2.0.1.Final'
这个根据大家具体的项目依赖构建方式而定,而选择对应的方式导入依赖。
Step 2: 创建验证实体类
假设我们有一个 RegistrationForm
,其中 name
必须填写有效字符,email
不能为 null
,age
则可以为空但如果填写必须为正数。
import javax.validation.constraints.NotNull;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Positive;
public class RegistrationForm {
@NotBlank(message = "用户名不能为空")
private String name;
@NotNull(message = "邮箱不能为空")
private String email;
@Positive(message = "年龄必须为正数")
private Integer age;
// Getter 和 Setter
}
Step 3: 在 Controller 中使用 @Validated
触发验证
在 Spring Boot 项目中,我们可以在 Controller 层使用 @Valid
注解来自动触发验证逻辑:
@RestController
@RequestMapping("/system/testUser")
public class RegistrationController {
/**
* 新增user
*/
@ApiOperation("新增user")
@PostMapping("/add")
public R<Void> add(@Validated @RequestBody User user) {
return toR(userService.insert(user));
}
}
Step 4: 捕获验证失败异常
为了更好地处理验证错误,我们可以创建一个全局异常处理器:
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public String handleValidationExceptions(MethodArgumentNotValidException ex) {
return ex.getBindingResult().getFieldError().getDefaultMessage();
}
}
这样一来,当输入的 name
是空字符串,email
是 null
时,系统会根据注解的 message
属性返回对应的错误提示。
Step 5: 实际演示
为了验证如上代码注解是否真正能够拦截这些情景,我们直接上Postman来模拟调用接口测试一下。
模拟场景1:用户名直接传空值
这里我们请求的时候,将name直接传null值进行请求。Postman请求如下:
如上成功验证若用户名传入空值则自动会被拦截,且提示对应的message信息,如“姓名不能为空”。
模拟场景2:邮箱号直接传null值
继续模拟,这里我们在发请求的时候,将email直接传null值。Postman请求如下:
如上成功验证邮箱号传null值依然会被拦截,强行提醒“邮箱不能为空”,告知用户其字段信息的校验规则。
模拟场景3:年龄直接传负值
继续模拟,这里我们在发请求的时候,将age直接传个负数。Postman请求如下:
如上成功验证年龄传负值也依然会被拦截,强行被提示“年龄必须为正数”。
总之,这里已经替大家都测试过了,大家可放心食用,根据不同的场景选择合适的校验注解。
🤔 它们与 @NotEmpty 有什么不同?
除了 @NotNull
和 @NotBlank
之外,@NotEmpty
也是一个常见的校验注解(这个我特地抽一期聊聊),特别是针对集合类时会经常使用。@NotEmpty
的含义介于 @NotNull
和 @NotBlank
之间,通常用于集合类或字符串,要求字段既不为 null
,也不能是空集合或空字符串。
三者的区别
@NotNull
:仅要求字段不为null
,允许空字符串或空集合。@NotEmpty
:不仅不为null
,还要求有内容,适用于集合或字符串。@NotBlank
:最严格,要求字段不为null
,且内容不为全空格,仅适用于字符串。
🛠️ 深度解析:底层原理与实现区别
在底层实现上,@NotNull
和 @NotBlank
都依赖于 Java Bean Validation 规范(JSR 380),通常由 Hibernate Validator 提供实现。以下是关于 @NotNull
和 @NotBlank
的底层原理与实现区别的对照:
对比维度 | @NotNull | @NotBlank |
---|---|---|
基本功能 | 检查对象是否为 null | 检查字符串是否既非 null 且包含至少一个非空白字符 |
适用类型 | 任意对象类型,包括 String 、集合、数值等 | 仅适用于 String 类型 |
校验规则 | 只需判断值是否为 null | 判断值是否为 null 去除首尾空格后判断是否为空字符串 |
实现类 | NotNullValidator | NotBlankValidator |
核心逻辑 | 使用 value != null 检测是否非空 | 使用 value != null && !value.trim().isEmpty() 检测是否包含有效字符 |
适用场景 | 确保字段被赋值 常用于对象引用的非空验证 | 确保字符串非空且有效 常用于用户输入、文本字段等 |
依赖库 | Hibernate Validator 或 Bean Validation(JSR 380) | Hibernate Validator 或 Bean Validation(JSR 380) |
典型应用场景 | 检查实体类中的复杂对象是否非空 | 检查表单输入或字符串字段是否包含有效字符 |
误用风险 | 无法检测字符串是否是空白字符(例如 " " ) | 无法应用于非字符串类型,如集合、数组等 |
总而言之:
- 使用
@NotNull
时,只关心值是否为null
,适用于所有对象类型。 - 使用
@NotBlank
时,不仅要检查非null
,还会去掉空格检查是否为空字符串,专用于字符串校验。
通过明确两者的差异,可以在实际开发中更精准地选择合适的校验注解,从而避免潜在问题。
💡 最佳实践与常见误区
-
针对字段类型选择正确的注解:当字段类型是字符串,且要求非空和非空白内容时使用
@NotBlank
,其他对象类型建议使用@NotNull
。 -
提供清晰的错误信息:在每个注解的
message
属性中设置用户友好的提示内容,这样当验证失败时,用户能得到明确的反馈。 -
避免误用:对于非字符串字段(如整数、集合等),不要使用
@NotBlank
,它只适用于字符串。使用@NotNull
和@NotEmpty
更适合。 -
结合使用多个注解:在实际项目中,可能需要更复杂的校验,可以将
@NotNull
与@Pattern
、@Size
等注解组合使用,实现更精准的控制。
📈 总结与心得
说到这儿,咱们就要说再见了,而你们才刚开始。我就简单概括一下:@NotNull
和 @NotBlank
这两是数据校验中非常重要的注解,它们虽然都与非空校验相关,但在实际应用中各有侧重:@NotNull
用于检查任意对象是否为 null
,而 @NotBlank
则专门针对字符串,确保其不仅非空,还必须包含至少一个非空白字符,所以大家要根据合适的场景进行使用,切不可乱用。
正确选择和使用这两个注解,可以有效保障输入数据的完整性与准确性。通过这篇文章,希望大家能更清晰地掌握 @NotNull
和 @NotBlank
的区别,避免在项目开发中踩坑!还没在项目中使用的,快动手在你的项目中尝试一下吧,合理运用这两个注解,助力你少些代码,释放双手,真可谓是谁用谁爽系列呢,OK,本期就说到这儿,咱们下期见🎉
📣 关于我
我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿哇。
-End-