springboot中使用Hibernate-Validation校验参数详解
作者:Geroge1226
1、说明
后端接口设计时候,需要对前端请求参数进行'先校验后处理业务'情况,如果在业务代码中通过类似if这里逐个校验,会使得代码变得繁琐,开发工作者都是爱偷懒的。java中,Bean Validation
为JavaBean
的验证定义了相关的元数据模型和API。
基于Bean-Validation
封装,提供了更加丰富的Hibernate-Validation
的校验包。也有开发会把这类校验交给前端来处理,但是接口暴露外网会存在直接调用情况(黄牛)。毕竟:前端校验是为了提高用户的体验度,后端校验则是为了保证数据的安全性
优点
1.验证逻辑与业务逻辑之间进行了分离,降低了程序耦合度
2.统一且规范的验证方式,无需你再次编写重复的验证代码
3.你将更专注于你的业务,将这些繁琐的事情统统丢在一边
2、Bean Validation与Hibernate Validation
2.1 Bean Validation中内置的constraint
包位置路径:javax.validation.constraints
注解 | 说明 |
---|---|
@AssertFalse | 注释的元素必须为False |
@AssertTrue | 注释的元素必须为True |
注释的元素必须邮箱 | |
@NotBlank | 注释的元素不能为空,!null && size>0 |
@NotEmpty | 注释的元素不能为空,数组,集合等 |
@NotNull | 注释的元素必须为空,但可以为""字符串 |
@DecimalMin | 注释的元素数字,最小不得小于Min |
@DecimalMax | 注释的元素为数字,最大不超过Max值 |
其中NotNull、NotEmpty、NotBlank区别
- @NotNull
适用于基本数据类型(Integer,Long,Double等等),当 @NotNull 注解被使用在 String 类型的数据上,则表示该数据不能为 Null(但是可以为 Empty) - @NotBlank
适用于 String 类型的数据上,加了@NotBlank 注解的参数不能为 Null 且 trim() 之后 size > 0 - @NotEmpty
适用于 String、Collection集合、Map、数组等等,加了@NotEmpty 注解的参数不能为 Null 或者 长度为 0
2.1 Hibernate Validation中添加的constraint
注解 | 说明 |
---|---|
@Length | 注释的元素字符串长度必须为制定返回内 |
@Range | 注释的元素必须在指定范围内 |
@URL | 注释的元素必须为链接 |
3、基于Hibernate Validation的实现
(1)pom包引用
查看spring-boot-start-web
中已经集成了Hibernate Validation
,所以可以不用额外引用包。同时spring-boot-start-validation
也完成了Hibernate Validation
的start
封装(校验机制更加全面)。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> <version>2.2.6.RELEASE</version> </dependency>
(2)Bean
对象中使用注解注释
... @ApiModelProperty(value = "收货人所在省",required = true) @NotNull(message = "省不能为空") private String recipientProvince; @ApiModelProperty(value = "收货人所在市") @NotNull(message = "市不能为空") private String recipientCity; @ApiModelProperty(value = "收货人所在区") @NotNull(message = "区不能为空") private String recipientDistrict; ...
(3)Controller
层使用@Valid
或者@Validated
@PostMapping("/add") public UniformResultTemplate<Boolean> addAddress(@RequestBody @Validated AddressReqDto reqDto, HttpServletRequest request){ return null; }
注意:Post请求方式区别,Get@Validated注解需要加在 所在方法类前
@RestController @RequestMapping("/api/address") @Validated public class AddressController extends BaseController{ @ApiOperation("收获地址详情") @GetMapping("/detail") public UniformResultTemplate<AddressDetailRespDto> queryAddressList(@NotNull(message = "地址Id不能为空") @RequestParam(value = "addressId") Long addressId, HttpServletRequest request){ return null; } }
(4)使用@ControllerAdvice
统一异常处理返回。
@Component @ControllerAdvice @Slf4j public class GlobalExceptionHandler { // Post请求Bean中的校验抛出:MethodArgumentNotValidException @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseBody public UniformResultTemplate handleBindException(MethodArgumentNotValidException ex) { FieldError fieldError = ex.getBindingResult().getFieldError(); log.warn("参数校验异常:{}({})", fieldError.getDefaultMessage(),fieldError.getField()); return new UniformResultTemplate("10002",fieldError.getDefaultMessage()); } // Get请求的参数校验,抛出的是ConstraintViolationException @ExceptionHandler(ConstraintViolationException.class) @ResponseBody public UniformResultTemplate handleGetBindException(ConstraintViolationException ex) { Set<ConstraintViolation<?>> eSet = ex.getConstraintViolations(); StringBuffer sb = new StringBuffer(); if(!CollectionUtils.isEmpty(eSet)) { Iterator<ConstraintViolation<?>> iterator = eSet.iterator(); while (iterator.hasNext()) { log.warn("参数校验异常:{}({})", iterator.next().getMessage()); sb.append(iterator.next().getMessage()).append("::"); } } return new UniformResultTemplate("10002",sb.toString()); } // 方法签名参数错误 @ExceptionHandler(MissingServletRequestParameterException.class) @ResponseBody public UniformResultTemplate handleGetBindException(MissingServletRequestParameterException ex) { log.warn("参数校验异常:{}", ex.getMessage()); return new UniformResultTemplate("10002",ex.getMessage()); } }
(5)结果现象
{
"code": "10002",
"message": "市不能为空",
"result": null,
"totalTimes": null,
"interfaceTimes": null
}
4、编译器校验工具
防止因使用错误Hibernate-Validation注解而导致程序运行时报错,增加编译器校验工具,进行友好提示。
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator-annotation-processor</artifactId> <version>6.1.5.Final</version> </dependency>
以上就是springboot中使用Hibernate-Validation校验参数详解的详细内容,更多关于springboot Hibernate-Validation的资料请关注脚本之家其它相关文章!