Validation 本身不是一个具体的依赖、实体类或单一的技术组件,而是一个广泛的概念,涉及数据验证的过程和机制。在软件开发中,特别是在Java及其生态系统中,Validation 指的是对输入数据进行校验,以确保其符合预期的格式、范围或业务规则的过程。
以下是关于Validation的几个方面:
1. Validation的概念
Validation是确保数据质量和一致性的重要步骤。在Web应用程序、桌面应用程序或任何需要用户输入的软件中,验证输入数据是否符合预期格式或业务逻辑是至关重要的。这有助于防止错误、提高数据质量和用户体验。
2. Validation的实现方式(springboot直接引入依赖即可)
在Java中,Validation可以通过多种方式实现,包括但不限于:
- 手动验证:通过编写if-else语句或循环来检查数据的合法性。
- 使用Validation API:如Bean Validation API(JSR 303、JSR 349、JSR 380等),它提供了一套注解和API来声明和执行验证规则。
- 框架集成:许多Java框架(如Spring框架)都集成了Validation API,并提供了额外的功能和简化用法。
3. Validation的依赖引入
当提到Validation的“依赖”时,通常指的是在项目中需要引入的库或模块,以便能够使用Validation功能。例如,在Spring Boot项目中,为了使用Bean Validation功能,通常需要添加spring-boot-starter-validation
依赖。这个依赖包含了必要的库,如Hibernate Validator,它是Bean Validation的一个实现。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
4. Validation的注解(通常在POJO类上使用标注)
Bean Validation API定义了一系列注解,用于声明验证规则。这些注解可以直接应用于JavaBean的字段、方法参数或返回类型上。常见的注解包括:
常见注解及其功能
- 空检查
@Null
:验证对象必须为null。@NotNull
:验证对象必须不为null,但无法检查长度为0的字符串。@NotBlank
:检查约束字符串是不是null且被trim后的长度是否大于0,只对字符串有效,且会去掉前后空格。@NotEmpty
:检查约束元素是否为null或者是空(对于字符串是长度为零,对于集合、数组是大小为0)-
@NotEmpty和@notNull的区别
@NotEmpty注解用于确保被注解的字段或参数不为null,并且其长度(对于字符串、集合、数组等)必须大于0。换句话说,它要求字段或参数必须包含至少一个元素或字符。不能为空字符。适用场景:
字符串:要求字符串至少包含一个非空白字符。
集合(如List、Set)、数组:要求集合或数组中至少有一个元素。
Map:要求Map中至少有一对键值对。
关键点:不能为null。
对于字符串,不能仅包含空白字符(如空格、制表符等)。
对于集合、数组和Map,不能为空(即必须包含至少一个元素或键值对)。
@NotNull
@NotNull注解用于确保被注解的字段或参数不为null。它不对字段或参数的内容(如字符串的长度、集合的大小,可以是空字符)进行任何限制。适用场景:
几乎适用于所有类型的字段或参数,包括基本数据类型(通过包装类)、对象、字符串、集合、数组等。
关键点:不能为null。
不关心字段或参数的具体内容,只要求它们存在(即非null)。
- 布尔值检查
@AssertTrue
:验证Boolean对象是否为true。@AssertFalse
:验证Boolean对象是否为false。
- 长度检查
@Size(min=, max=)
:验证对象(Array、Collection、Map、String)的长度是否在给定的范围之内。@Length(min=, max=)
(Hibernate Validator特有):验证字符串的长度是否在指定的范围内。
- 日期检查
@Past
:验证Date和Calendar对象是否在当前时间之前。@Future
:验证Date和Calendar对象是否在当前时间之后。
- 数值检查
@Min(value)
:验证Number和String对象是否大于等于指定的最小值。@Max(value)
:验证Number和String对象是否小于等于指定的最大值。@DecimalMin(value)
:验证被标注的值必须大于等于指定的最小值。@DecimalMax(value)
:验证被标注的值必须小于等于指定的最大值。@Digits(integer=, fraction=)
:验证数值的整数部分和小数部分是否在指定范围内。
- 正则表达式
@Pattern(regexp=, flags=)
:验证String对象是否符合正则表达式的规则。
- 范围检查
@Range(min=, max=)
:被注释的元素必须在合适的范围内(适用于BigDecimal、BigInteger、byte、short、int、long,以及包装类型)。
- 其他
@Email
:验证字符串是否为电子邮件地址(Hibernate Validator扩展)。@Valid
:递归地对关联对象进行校验,如果关联对象是个集合或者数组,那么对其中的元素进行递归校验;如果是一个Map,则对其中的值部分进行校验。
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
public class User {
@NotNull(message = "ID不能为空")
private Long id;
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 30, message = "用户名长度必须在2到30个字符之间")
private String username;
@NotBlank(message = "邮箱不能为空")
@Email(message = "邮箱格式不正确")
private String email;
// 省略getter和setter方法
}
5. Validation在Controller中的启用
在Spring MVC的控制器中,使用@Valid
或@Validated
注解来启用验证。当请求到达控制器时,Spring会自动根据注解对请求参数进行验证。
例如,在UserController
中处理用户注册请求:
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping("/register")
public ResponseEntity<String> register(@Validated @RequestBody User user) {
// 如果验证失败,Spring会自动抛出异常并处理
// 这里只处理验证通过的情况
return ResponseEntity.ok("注册成功");
}
}
在Spring框架中,特别是Spring MVC和Spring Boot中,Validation得到了广泛的支持和简化。开发者可以通过在Controller的方法参数上添加@Valid
或@Validated
注解,并结合Bean Validation注解来自动进行输入验证。如果验证失败,Spring会自动处理错误,并可以通过自定义的全局异常处理器来返回友好的错误消息。
功能特点
- 注解驱动:Bean Validation规范定义了一套注解,开发者可以直接将这些注解加在JavaBean的属性、方法参数或返回值上,以声明验证规则。
- 运行时验证:验证是在运行时进行的,验证失败后会立即返回错误信息。
- 可扩展性:除了使用内置的注解外,开发者还可以编写自定义的注解和验证器,以满足特定的验证需求。
- 与框架集成:Bean Validation API与Spring、Hibernate等框架集成良好,可以方便地在这些框架中使用验证功能。
6.分组校验(可选)
在Validation中,分组校验允许你为不同的验证场景定义不同的验证规则。这是通过为验证注解指定分组来实现的。每个分组都是一个Java接口,通常不包含任何方法,只是用作标记。
实现步骤
-
定义分组接口:
首先,你需要定义一些分组接口,这些接口将用作验证注解的参数,以指示哪些验证规则应用于特定的验证场景。public interface FirstGroup {} public interface SecondGroup {}
-
在模型类中使用分组:
在你的模型类中,使用验证注解,并通过groups
属性指定分组。public class User { @NotNull(groups = FirstGroup.class, message = "ID不能为空") private Long id; @NotBlank(groups = FirstGroup.class, message = "用户名不能为空") @Size(min = 2, max = 30, groups = FirstGroup.class, message = "用户名长度必须在2到30个字符之间") private String username; @NotBlank(groups = SecondGroup.class, message = "邮箱不能为空") @Email(groups = SecondGroup.class, message = "邮箱格式不正确") private String email; // 省略getter和setter方法 }
-
在控制器中使用分组:
在你的控制器中,使用@Validated
注解,并通过value
属性指定要应用的分组。@RestController @RequestMapping("/users") public class UserController { @PostMapping("/register") public ResponseEntity<String> register(@Validated(FirstGroup.class) @RequestBody User user) { // 处理注册逻辑 return ResponseEntity.ok("注册成功"); } @PutMapping("/updateEmail") public ResponseEntity<String> updateEmail(@Validated(SecondGroup.class) @RequestBody User user) { // 处理更新邮箱逻辑 return ResponseEntity.ok("邮箱更新成功"); } }
注意事项
- 分组接口通常不包含任何方法,它们只是用作标记。
- 你可以定义任意数量的分组接口,以满足不同的验证需求。
- 在控制器中,你可以通过
@Validated
注解的value
属性指定要应用的分组。 - 如果验证失败,Spring会抛出
MethodArgumentNotValidException
异常,你可以通过全局异常处理器来捕获并处理这个异常。
通过分组校验,你可以灵活地定义和应用不同的验证规则,以满足不同的业务场景需求。
7.默认分组
在Spring框架中,@Validated
注解用于开启数据验证功能。当你使用这个注解时,你可以指定一个或多个验证分组,这些分组决定了哪些验证规则将被应用。
@Validated
注解有一个value
属性,它接受一个Class类型的数组,用于指定要应用的验证分组。如果你没有为这个属性指定任何值,那么Spring将默认归为默认分组中。
默认分组在Spring的验证框架中是预定义的,它对应于javax.validation.groups.Default
接口。当你没有为@Validated
注解指定任何分组时,Spring将自动使用默认分组来验证你的数据。
这意味着,如果你的模型类中的验证注解没有指定分组,或者指定了Default
分组,那么这些验证规则将在使用@Validated
注解但没有指定分组的情况下被应用。
例如,以下是一个模型类,其中的验证注解没有指定分组,因此它们将属于默认分组:
public class User {
@NotNull(message = "ID不能为空")
private Long id;
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 30, message = "用户名长度必须在2到30个字符之间")
private String username;
// 省略getter和setter方法
}
在控制器中,如果你使用@Validated
注解但没有指定分组,那么默认分组的验证规则将被应用:
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping("/register")
public ResponseEntity<String> register(@Validated @RequestBody User user) {
// 处理注册逻辑
return ResponseEntity.ok("注册成功");
}
}
在分组验证中,也可以使用Default.class,减少代码数量。第一次玩CSDN,搞不懂字体。
8. 补充:message属性
在验证注解中,message
属性用于定义当验证规则失败时返回的错误消息。当你使用如 @NotNull
、@NotBlank
、@Size
等验证注解时,你可以通过 message
属性来指定一个自定义的错误消息,这个消息会在验证失败时被返回。
例如,在以下模型类中:
public class User {
@NotNull(message = "ID不能为空")
private Long id;
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 30, message = "用户名长度必须在2到30个字符之间")
private String username;
// 省略getter和setter方法
}
如果 id
字段为 null
,那么验证将失败,并返回 "ID不能为空"
这个错误消息。同样,如果 username
字段为空或长度不在2到30个字符之间,也会返回相应的错误消息。
这些错误消息对于前端开发者来说非常有用,因为它们可以直接显示给用户,告诉用户输入的数据有什么问题。同时,对于后端开发者来说,这些错误消息也有助于调试和跟踪问题。
在Spring框架中,当验证失败时,这些错误消息会被封装在一个 BindingResult
对象或 MethodArgumentNotValidException
异常中,你可以在你的控制器中访问这些错误消息,并将它们以适当的方式返回给前端。