目录
1.MethodArgumentNotValidException异常
3.ConstraintViolationException异常
一.Spring validate 是什么
Spring Validate 是 Spring 框架提供的一个用于数据校验的模块。它提供了一种方便的方式来验证应用程序中的数据,例如用户输入、请求参数等。通过使用 Spring Validate,您可以定义验证规则,并在数据不符合这些规则时抛出异常,从而确保数据的完整性和准确性。
Spring Validate 提供了以下功能:
注解验证:使用注解来定义验证规则,例如 @NotNull、@Size 等。这些注解可以应用于类、字段或方法上,以便在运行时进行验证。
自定义验证器:您可以使用自定义验证器来定义自己的验证规则。自定义验证器可以扩展 Spring 的 Validator 接口,并实现 validate() 方法来执行自定义的验证逻辑。
校验分组:您可以根据不同的需求将校验规则分组,并在运行时选择要应用的组。这对于在不同场景下使用不同的校验规则非常有用。
错误处理:如果数据不符合验证规则,Spring Validate 将抛出 ConstraintViolationException 异常。您可以使用 @ControllerAdvice 注解和 @ExceptionHandler 方法来处理这些异常,并返回适当的错误消息给用户。
总的来说,Spring Validate 是一个强大的工具,可以帮助您在 Spring 应用程序中确保数据的完整性和准确性。通过使用注解和自定义验证器,您可以轻松地定义验证规则,并在运行时执行这些规则来确保数据的正确性。
二.Spring validate的主要功能及作用
Spring Validate主要功能包括但不限于:
参数校验:Spring Validate可以用于对Controller层中接收的参数进行校验,包括请求参数、用户输入等。通过注解的方式,可以方便地定义验证规则,例如非空验证、长度验证等。
数据完整性验证:在数据传输和存储过程中,可能会遇到数据被篡改或损坏的情况。通过Spring Validate对数据进行校验,可以确保数据的完整性和准确性。
自定义校验规则:如果默认的验证规则不能满足需求,Spring Validate允许自定义校验规则。用户可以扩展验证器接口,实现自定义的验证逻辑。
错误处理:当数据不符合验证规则时,Spring Validate会抛出异常。通过捕获并处理这些异常,可以在前端页面上展示错误信息,或者在日志中记录错误信息。
校验分组:可以将校验规则分组,并在运行时选择要应用的组。这可以帮助在不同的场景下使用不同的校验规则。
三.Spring validate如何使用
1.引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2.参考实体类
以下是带有大部分验证注解的参考实体类
@Data
public class Student {
/**
* 学生姓名
* - 不允许为空
* - 长度必须在2到30个字符之间
*/
@NotNull(message = "姓名不能为空")
@Size(min = 2, max = 30, message = "姓名长度必须在2到30个字符之间")
private String name;
/**
* 学生邮箱
* - 必须是有效的电子邮件地址
* - 不允许为空
*/
@Email(message = "邮箱地址格式不正确")
@NotEmpty(message = "邮箱不能为空")
private String email;
/**
* 学生年龄
* - 必须在18到100岁之间
*/
@Min(value = 18, message = "年龄必须至少18岁")
@Max(value = 100, message = "年龄必须不超过100岁")
private int age;
/**
* 学生用户名
* - 必须是5到10个字母数字字符
*/
@Pattern(regexp = "^[a-zA-Z0-9]{5,10}$", message = "用户名必须是5到10个字母数字字符")
private String username;
/**
* 学生金额
* - 必须在0.01到1000.00之间
*/
@DecimalMin(value = "0.01", message = "金额必须至少0.01")
@DecimalMax(value = "1000.00", message = "金额必须不超过1000.00")
private BigDecimal amount;
/**
* 学生激活状态
* - 必须为true
*/
@AssertTrue(message = "激活状态必须为true")
private boolean active;
/**
* 学生删除状态
* - 必须为false
*/
@AssertFalse(message = "删除状态必须为false")
private boolean deleted;
/**
* 学生开始日期
* - 必须在将来
*/
@Future(message = "开始日期必须在将来")
private Date startDate;
/**
* 学生出生日期
* - 必须在过去
*/
@Past(message = "出生日期必须在过去")
private Date birthDate;
/**
* 学生预约日期
* - 必须在将来或今天
*/
@FutureOrPresent(message = "预约日期必须在将来或今天")
private LocalDate appointmentDate;
/**
* 学生注册日期
* - 必须在过去或今天
*/
@PastOrPresent(message = "注册日期必须在过去或今天")
private LocalDate registrationDate;
}
注: 以下是常用于非空判断的注解及区别
@NotNull:适用于任何类型,不能为null,但可以是 ("")
@NotBlank:只能用于 String,不能为null,而且调用 trim() 后,长度必须大于0,必须要有实际字符。
@NotEmpty:用于 String、Collection、Map、Array,不能为null,长度必须大于0。
四.三种校验方式,返回的异常类型及方式
1.MethodArgumentNotValidException异常
在需要校验的对象前面加 @RequestBody注解以及@Validated或者@Valid注解,如果校验失败,会抛出MethodArgumentNotValidException异常
@RestController
public class VerifyController {
@PostMapping("save")
public void save(@RequestBody @Validated Student student) {
System.out.println("校验失败,会抛出MethodArgumentNotValidException异常");
}
}
2.BindException异常
在需要校验的对象前面不加@RequestBody注解,使用@Validated或者@Valid注解,如果校验失败,会抛出BindException异常
@RestController
public class VerifyController {
@PostMapping("save")
public void save(@Validated Student student) {
System.out.println("校验失败,会抛出BindException异常");
}
}
3.ConstraintViolationException异常
路径传参,在参数前面加上相对应的校验注解,还必须在Controller类上加 @Validated注解。如果校验失败,会抛出ConstraintViolationException异常
/**
* 控制器类,用于处理保存用户信息的请求。
* 使用了 {@link Validated} 注解来启用参数验证。
*/
@RestController
@Validated
public class VerifyController {
/**
* 处理保存用户信息的 POST 请求。
* 该方法接收两个请求参数:`name` 和 `age`。
*
* @param name 用户名,使用 {@link NotBlank} 注解确保其不为空或只包含空白字符。
* 如果 `name` 为空或只包含空白字符,会抛出 {@link ConstraintViolationException} 异常。
* @param age 用户年龄,使用 {@link NotNull} 注解确保其不为 null。
* 如果 `age` 为 null,会抛出 {@link ConstraintViolationException} 异常。
*/
@PostMapping("save")
public void save(@NotBlank(message = "name不能为空") String name, @NotNull(message = "age不能为空") Integer age) {
System.out.println("校验失败,会抛出ConstraintViolationException异常");
}
}
注: 请求路径类似于: http://localhost:8080/save?name=&age=25
五.编写统一异常处理类
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理 {@link MethodArgumentNotValidException} 异常。
* 当请求体(@RequestBody)中的数据验证失败时,会抛出此异常。
* 该方法会从异常中提取所有验证错误信息,并返回一个包含所有错误信息的字符串。
*
* @param e MethodArgumentNotValidException 异常对象
* @return 包含所有验证错误信息的字符串
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public String handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
String messages = bindingResult.getAllErrors()
.stream()
.map(ObjectError::getDefaultMessage)
.collect(Collectors.joining(";"));
return messages;
}
/**
* 处理 {@link BindException} 异常。
* 当表单数据绑定失败或验证失败时,会抛出此异常。
* 该方法会从异常中提取所有验证错误信息,并返回一个包含所有错误信息的字符串。
*
* @param e BindException 异常对象
* @return 包含所有验证错误信息的字符串
*/
@ExceptionHandler(value = BindException.class)
public String exceptionHandler(BindException e) {
String messages = e.getBindingResult().getAllErrors()
.stream()
.map(ObjectError::getDefaultMessage)
.collect(Collectors.joining(";"));
return messages;
}
/**
* 处理 {@link ConstraintViolationException} 异常。
* 当请求参数(@RequestParam)上的数据验证失败时,会抛出此异常。
* 该方法会从异常中提取所有验证错误信息,并返回一个包含所有错误信息的字符串。
*
* @param exception ConstraintViolationException 异常对象
* @return 包含所有验证错误信息的字符串
*/
@ExceptionHandler({ConstraintViolationException.class})
public String methodArgumentNotValid(ConstraintViolationException exception) {
String message = exception.getConstraintViolations().stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.joining(";"));
return message;
}
}
六.validate校验注解合集
| 注解 | 解释 | 适用类型 | null值有效 | 示例 |
| @AssertFalse | 验证元素值是 false | boolean, Boolean | 否 | @AssertFalse(message = "必须为 false") private boolean active; |
| @AssertTrue | 验证元素值是 true | boolean, Boolean | 否 | @AssertTrue(message = "必须为 true") private boolean active; |
| @DecimalMax(value) | 验证 BigDecimal、BigInteger、 long、Long、int、 Integer、short、Short、 byte、Byte、double、 Double、float、Float 值小于等于给定的最大值 | String, BigDecimal,BigInteger, long,Long,int, Integer,short,Short, byte,Byte,double, Double,float,Float | 是 | @DecimalMax(value = "100", message = "不能超过100") private int age; |
| @DecimalMin(value) | 验证 BigDecimal、BigInteger、 long、Long、int、 Integer、short、Short、 byte、Byte、double、 Double、float、Float 值大于等于给定的最小值 | String, BigDecimal,BigInteger, long,Long,int, Integer,short,Short, byte,Byte,double, Double,float,Float | 是 | @DecimalMin(value = "18", message = "不能低于18") private int age; |
| @Digits(integer, fraction) | 验证 BigDecimal、 BigInteger、long、Long、 int、Integer、short、 Short、byte、Byte 值的整数部分和小数部分的位数 | String,BigDecimal, BigInteger,long,Long, int,Integer,short, Short,byte,Byte | 是 | @Digits(integer=3, fraction=2, message = "最多3位整数和2位小数") private BigDecimal price; |
| | 验证元素值是有效的电子邮件地址 | CharSequence | 是 | @Email(message = "无效的电子邮件地址") private String email; |
| @Future | 验证 Date、Calendar、Temporal 值是在未来的时间 | java.util.Date, java.util.Calendar, java.time.Temporal | 是 | @Future(message = "必须是未来的日期") private LocalDate dateOfBirth; |
| @FutureOrPresent | 验证 Date、Calendar、Temporal 值是在未来或当前的时间 | java.util.Date, java.util.Calendar, java.time.Temporal | 是 | @FutureOrPresent(message = "必须是未来或当前的日期") private LocalDate startDate; |
| @Max(value) | 验证 BigDecimal、BigInteger、 long、Long、int、 Integer、short、Short、 byte、Byte、double、 Double、float、Float 值小于等于给定的最大值 | long,Long,int, Integer,short,Short, byte,Byte,double, Double,float,Float | 是 | @Max(value = 100, message = "不能超过100") private int age; |
| @Min(value) | 验证 BigDecimal、BigInteger、 long、Long、int、 Integer、short、Short、 byte、Byte、double、 Double、float、Float 值大于等于给定的最小值 | long,Long,int, Integer,short,Short, byte,Byte,double, Double,float,Float | 是 | @Min(value = 18, message = "不能低于18") private int age; |
| @Negative | 验证 BigDecimal、BigInteger、 long、Long、int、 Integer、short、Short、 byte、Byte、double、 Double、float、Float 值小于零 | BigDecimal,BigInteger, long,Long,int, Integer,short,Short, byte,Byte,double, Double,float,Float | 是 | @Negative(message = "必须小于0") private int value; |
| @NegativeOrZero | 验证 BigDecimal、BigInteger、 long、Long、int、 Integer、short、Short、 byte、Byte、double、 Double、float、Float 值小于等于零 | BigDecimal,BigInteger, long,Long,int, Integer,short,Short, byte,Byte,double, Double,float,Float | 是 | @NegativeOrZero(message = "必须小于等于0") private int value; |
| @NotNull | 验证元素值不为 null | 任何类型 | 否 | @NotNull(message = "不能为空") private String name; |
| @Null | 验证元素值为 null | 任何类型 | 是 | @Null(message = "必须为 null") private String name; |
| @Past | 验证 Date、Calendar、Temporal 值是在过去的时间 | java.util.Date, java.util.Calendar, java.time.Temporal | 是 | @Past(message = "必须是过去的日期") private LocalDate dateOfBirth; |
| @PastOrPresent | 验证 Date、Calendar、Temporal 值是在过去或当前的时间 | java.util.Date, java.util.Calendar, java.time.Temporal | 是 | @PastOrPresent(message = "必须是过去或当前的日期") private LocalDate startDate; |
| @Pattern(regexp) | 验证元素值符合正则表达式 | CharSequence | 是 | @Pattern(regexp="^[a-zA-Z0-9]+$", message = "只能包含字母和数字") private String code; |
| @Positive | 验证 BigDecimal、 BigInteger、long、 Long、int、Integer、 short、Short、byte、 Byte、double、 Double、float、Float 值大于零 | BigDecimal,BigInteger, long,Long,int, Integer,short,Short, byte,Byte,double, Double,float,Float | 是 | @Positive(message = "必须大于0") private int value; |
| @PositiveOrZero | 验证 BigDecimal、BigInteger、 long、Long、int、 Integer、short、Short、 byte、Byte、double、 Double、float、Float 值大于等于零 | BigDecimal,BigInteger, long,Long,int, Integer,short,Short, byte,Byte,double, Double,float,Float | 是 | @PositiveOrZero(message = "必须大于等于0") private int value; |
| @Size(min, max) | 验证集合、数组、字符串的长度在给定范围内 | CharSequence, Collection,Map, 数组 | 是 | @Size(min=2, max=10, message = "长度必须在2到10之间") private List items; |
3936

被折叠的 条评论
为什么被折叠?



