关于Spring Validation
Spring Validation是用于检查参数的基本格式有效性的框架
在项目中添加spring-boot-starter-validation依赖项:
<!-- Spring Boot支持Spring Validation的依赖项,用于检查参数的基本有效性 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
提示:在学习时,为了更清楚的了解执行过程,建议暂时不启用全局异常处理器!
检查POJO类型的参数
在需要被检查的参数前添加@Validated或@Valid注解,表示需要检查此参数,例如:
@PostMapping("/add-new")
// ↓↓↓↓↓↓ 新增注解
public JsonResult addNew(@Valid AlbumAddNewDTO albumAddNewDTO) {
//
}
然后,在POJO类型的属性上使用“检查注解”(例如:@NotNull表示“不允许为null”)来配置检查规则,例如:
@Data
public class AlbumAddNewDTO implements Serializable {
@NotNull // 新增注解
private String name;
// 暂不关心其它代码
}
当客户端提交的请求中不包含name属性时,服务器端将响应400错误!并且,在服务器端的控制台会有以下警告信息:
2023-02-24 14:42:16.018 WARN 22020 --- [nio-8080-exec-6] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors<EOL>Field error in object 'albumAddNewDTO' on field 'name': rejected value [null]; codes [NotNull.albumAddNewDTO.name,NotNull.name,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [albumAddNewDTO.name,name]; arguments []; default message [name]]; default message [不能为null]]
处理检查失败时异常
当检查失败时,Spring Validation框架会抛出BindException,同时,此框架还有DefaultHandlerExceptionResolver对此异常进行处理,以至于默认的失败效果是响应400错误。
可以在全局异常处理器中添加处理BindException异常的方法:
@ExceptionHandler
public JsonResult handleBindException(BindException e) {
String message = "请求参数格式错误!!!";
return JsonResult.fail(ServiceCode.ERROR_BAD_REQUEST, message);
}
在处理异常时,应该对错误的原因进行更加精准的描述,此描述文本需要通过检查注解的message属性进行配置,例如:
@Data
public class AlbumAddNewDTO implements Serializable {
@NotNull(message = "必须填写相册名称!") // 配置注解参数
private String name;
// 暂不关心其它代码
}
然后,在处理异常时,可以通过BindException对象的getFieldError().getDefaultMessage()获取此信息,例如:
@ExceptionHandler
public JsonResult handleBindException(BindException e) {
String message = e.getFieldError().getDefaultMessage();
return JsonResult.fail(ServiceCode.ERROR_BAD_REQUEST, message);
}
但是,当同时存在多种错误时,以上处理方式只能提示多种错误中的某1种,如果需要提示全部错误,需要调整为:
@ExceptionHandler
public JsonResult handleBindException(BindException e) {
StringBuilder stringBuilder = new StringBuilder();
List<FieldError> fieldErrors = e.getFieldErrors();
for (FieldError fieldError : fieldErrors) {
stringBuilder.append(fieldError.getDefaultMessage());
}
String message = stringBuilder.toString();
return JsonResult.fail(ServiceCode.ERROR_BAD_REQUEST, message);
}
关于快速失败
快速失败表现为:当检查参数的格式不通过时,不再继续对其它参数的检查!
相关配置代码如下:
package cn.tedu.csmall.product.config;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.validation.Validation;
/**
* Validation配置类
*
* @author java@tedu.cn
* @version 0.0.1
*/
@Slf4j
@Configuration
public class ValidationConfiguration {
public ValidationConfiguration() {
log.debug("创建配置类对象:ValidationConfiguration");
}
@Bean
public javax.validation.Validator validator() {
return Validation.byProvider(HibernateValidator.class)
.configure() // 开始配置
.failFast(true) // 配置快速失败
.buildValidatorFactory() // 构建Validator工厂
.getValidator(); // 从Validator工厂中获取Validator对象
}
}
检查简单类型参数
当需要检查简单类型的参数时,需要先在当前类上添加@Validated注解,例如:
@RestController
@RequestMapping("/album")
@Validated // 新增
public class AlbumController {
// 暂不关心
}
然后,在需要检查的参数上添加检查注解,例如:
@PostMapping("/delete")
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 检查注解的配置
public JsonResult delete(@RequestParam @Range(min = 1) Long id) {
albumService.delete(id);
return JsonResult.ok();
}
提示:以上参数上的@RequestParam只是临时使用的,如果没有此注解,在API文档的调试界面中暂时无法显示参数的输入框。
当提交的请求参数id值小于1时,会响应500错误,并且在服务器端的控制台会提示错误,例如:
javax.validation.ConstraintViolationException: delete.id: 需要在1和9223372036854775807之间
则可以在全局异常处理器中添加处理以上异常的方法:
@ExceptionHandler
public JsonResult handleConstraintViolationException(ConstraintViolationException e) {
StringBuilder stringBuilder = new StringBuilder();
Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
for (ConstraintViolation<?> constraintViolation : constraintViolations) {
stringBuilder.append(constraintViolation.getMessage());
}
String message = stringBuilder.toString();
return JsonResult.fail(ServiceCode.ERROR_BAD_REQUEST, message);
}
常用检查注解
使用Spring Validation框架时,常用的检查注解有:
@NotNull:不允许为null值,即客户端必须提交此参数
@NotEmpty:不允许为空值,即长度为0的字符串
仅能作用于字符串类型的参数
@NotBlank:不允许为空白值,即仅由空格、TAB、换行符组成的字符串
仅能作用于字符串类型的参数
@Pattern:通过此注解的regexp属性指定正则表达式,检查参数是否匹配此正则表达式
仅能作用于字符串类型的参数
@Range:限制数值型的参数值的有效区间
仅能作用于数值型的参数
以上2个注解可以同时添加在1个参数上。
以上@Range仅当参数值存在时执行检查,如果调用此方法时,传入的参数值为null,则此注解是无效的!所以,这类注解通常与@NotNull一起使用!
在源代码中,按住Ctrl键点击检查注解所在的包