1.spring-boot-starter-validation依赖
spring-boot-starter-validation
是 Spring Boot 提供的一个 starter 依赖,它整合了验证相关的所有依赖,简化了使用过程。这个 starter 会自动引入以下两个主要依赖:
-
jakarta.validation-api
:提供验证的规范和接口(如@NotBlank
、@Pattern
等注解)。 -
hibernate-validator
:作为验证规范的实现,执行实际的校验工作。
引入:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2.常用的注解
@NotNull
用于确保字段不为 null
。
如果字段为 null
,将触发验证失败。
import javax.validation.constraints.NotNull;
public class User {
@NotNull(message = "用户名不能为空")
private String username;
}
@NotBlank
用于确保字段不为 null
且不为空字符串。适用于 String
类型字段,验证内容是否为空(包括空格)。
import javax.validation.constraints.NotBlank;
public class User {
@NotBlank(message = "用户名不能为空")
private String username;
}
@NotEmpty
与 @NotBlank
类似,但适用于所有类型,确保集合、数组等不为空。
import javax.validation.constraints.NotEmpty;
public class User {
@NotEmpty(message = "邮箱不能为空")
private List<String> emails;
}
@Size
用于验证字符串、集合、数组等的大小是否符合要求。
import javax.validation.constraints.Size;
public class User {
@Size(min = 5, max = 20, message = "用户名长度必须在5到20个字符之间")
private String username;
}
@Pattern
用于正则表达式验证,验证字符串是否符合给定的模式。
import javax.validation.constraints.Pattern;
public class User {
@Pattern(regexp = "^[a-zA-Z]{6,}$", message = "用户名必须是至少6个字母")
private String username;
}
@Min 和 @Max
用于验证数值是否在指定的最小值或最大值之间。适用于 int
, long
, float
, double
等。
import javax.validation.constraints.Min;
import javax.validation.constraints.Max;
public class Product {
@Min(value = 1, message = "价格必须大于等于1")
@Max(value = 1000, message = "价格必须小于等于1000")
private double price;
}
用于验证字段是否为有效的电子邮件地址。
import javax.validation.constraints.Email;
public class User {
@Email(message = "请输入有效的邮箱地址")
private String email;
}
@Future 和 @Past
用于验证日期是否在未来或过去。
import javax.validation.constraints.Future;
import java.util.Date;
public class Event {
@Future(message = "事件日期必须是未来的日期")
private Date eventDate;
}
@Valid
用于嵌套对象的校验。将该注解放在另一个对象字段上,表示该字段对象需要进行验证。
import javax.validation.Valid;
public class User {
@Valid
private Address address;
}
public class Address {
@NotNull(message = "地址不能为空")
private String addressLine;
}
3.使用这些注解的步骤:
-
添加依赖
确保项目中已经加入了spring-boot-starter-validation
依赖。 -
在 Bean 中使用注解
如上面所示,你可以在 Java Bean 的字段上直接使用这些验证注解。 -
使用
@Valid
或@Validated
进行校验
在 Controller 中,你可以使用@Valid
或@Validated
注解来触发验证。
import javax.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@PostMapping("/register")
public Result register(@Valid @RequestBody User user) {
// 注册逻辑
}
- 处理验证错误
你可以使用BindingResult
来捕获验证结果,或者让 Spring 自动处理验证错误,返回 400 错误。
4.@valid和@Validated的区别和使用场景
@Valid 注解
- @Valid 注解用于触发 对象级别的验证,例如在控制器方法中对请求参数、请求体、或方法参数进行验证。
@Valid
本身没有分组验证功能,它的主要作用是简单地触发验证机制。
使用场景:
- 当你想对方法参数或字段进行简单的验证时,使用
@Valid
。
package com.akbar.controller;
import com.akbar.service.AdminService;
import com.akbar.util.Result;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/admin")
// 因为我暂时没有分组校验的需求,所以可以只使用@valid
@Valid
public class AdminController {
private final AdminService adminService;
@Autowired
public AdminController(AdminService adminService) {
this.adminService = adminService;
}
// 管理员注册
@PostMapping
public Result<Void> register(
@RequestParam
@NotBlank(message = "用户名不能为空")
@Pattern(regexp = "^[a-zA-Z]{5,}$", message = "用户名必须是至少5个字母,并且只能包含英文字母")
String username,
@RequestParam
@NotBlank(message = "密码不能为空")
@Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*\d)[A-Za-z\d]{8,}$", message = "密码必须包含字母和数字,且至少8个字符")
String password,
@RequestParam
@NotBlank(message = "确认密码不能为空")
String confirmPassword) {
if (!password.equals(confirmPassword)) {
return Result.error("密码和确认密码不匹配!");
}
boolean result = adminService.registerAdmin(username, password);
if (!result) {
return Result.error("用户名已存在!");
}
return Result.success("注册成功!");
}
}
什么是分组校验
你可以为验证规则定义不同的分组,然后在调用时指定需要验证的分组,控制哪些验证规则应该被触发。
比如下面的代码:
package com.akbar.pojo;
import com.akbar.anno.State;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.constraints.URL;
import java.time.LocalDateTime;
@TableName(value = "article")
public class Article {
@TableId(value = "id", type = IdType.AUTO)
@NotNull(groups = Article.Update.class) // 属于Update分组
private Integer id;
@TableField(value = "title")
@NotEmpty(groups = Article.Add.class, message = "文章标题不能为空!") // 属于Add分组
@Pattern(regexp = "^\S{1,30}$",message = "文章标题是1到30个字符!")
private String title;
@TableField(value = "summary")
private String summary;
@TableField(value = "content")
@NotEmpty(groups = Article.Add.class, message = "文章内容不能为空!") // 属于Add分组
private String content;
...
// 定义验证分组,定义了两个分组,分别是Add和Update
public interface Add {
}
public interface Update {
}
/*-----------------------getter,setter---------------*/
.....
}
在控制器中这样使用:
//更新文章
@PutMapping
// 当Update的时候触发相应分组中的校验规则
public Result update(@RequestBody @Validated(Article.Update.class) Article article) {
boolean updateResult = articleService.update(article);
if (updateResult) {
return Result.success();
} else {
return Result.error("该文章标题已经存在!");
}
}
//新增文章
@PostMapping
// 当Add的时候触发相应分组中的校验规则
public Result add(@RequestBody @Validated(Article.Add.class) Article article) {
boolean addResult = articleService.add(article);
if (addResult) {
return Result.success();
} else {
return Result.error("文章添加失败!");
}
}
@Validated 注解
-
@Validated
是 Spring Framework 提供的注解,主要用于支持 分组验证(grouped validation)。 -
它是 Spring 中
@Valid
的增强版,提供了额外的功能,特别是支持通过 分组 来控制验证的范围。
什么时候使用 @Valid
,什么时候使用 @Validated
-
使用
@Valid
:- 如果你没有涉及到 分组验证,并且只需要进行简单的验证,使用
@Valid
就足够了。 - 适用于不需要控制验证范围的场景,例如直接验证方法参数、请求体等。
- 如果你没有涉及到 分组验证,并且只需要进行简单的验证,使用
-
使用
@Validated
:- 如果你需要根据不同的 验证分组 来控制验证的范围,或者你希望对不同的验证场景进行不同的校验,可以使用
@Validated
。 - 适用于更复杂的验证场景,例如创建时验证某些字段,更新时验证其他字段。
- 如果你需要根据不同的 验证分组 来控制验证的范围,或者你希望对不同的验证场景进行不同的校验,可以使用