简介

JSR是Java Specification Requests的缩写,意思是Java 规范提案。

JSR-303 是JAVA EE 6 中的一项子规范,叫做Bean Validation,为Bean验证定义了元数据模型和API。

默认的元数据模型是通过Annotations来描述的,但是也可以使用XML来重载或者扩展。

常用校验注解

  1. Bean Validation 中内置的 constraint

    Constraint 详细信息
    @Null 被注释的元素必须为 null
    @NotNull 被注释的元素必须不为 null
    @AssertTrue 被注释的元素必须为 true
    @AssertFalse 被注释的元素必须为 false
    @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
    @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
    @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
    @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
    @Size(max, min) 被注释的元素的大小必须在指定的范围内
    @Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
    @Past 被注释的元素必须是一个过去的日期
    @Futuret 被注释的元素必须是一个将来的日期
    @Pattern(value) 被注释的元素必须符合指定的正则表达式
  2. Hibernate Validator 附加的 constraint

    Constraint 详细信息
    @Email 被注释的元素必须是电子邮箱地址
    @Length 被注释的字符串的大小必须在指定的范围内
    @NotEmpty 被注释的字符串的必须非空
    @Range 被注释的元素必须在合适的范围内

使用

引入依赖

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version>
</dependency>

定义校验规则

image-20240423201314654

添加@Vaild注解

image-20240423193729176

测试

校验通过

image-20240423194147124

校验不通过

image-20240423195715266

异常信息封装

如果只做以上的配置,无法在接口响应中看到异常信息,需要使用BindingResultMethodArgumentNotValidException异常信息绑定,然后自定义输出。

image-20240423204051658

注意:@Valid或@Validate的参数后必须紧挨着一个BindingResult 参数,否则spring会在校验不通过时直接抛出异常。

image-20240423201138021

image-20240423201242233

全局统一异常处理

在实际开发中,我们基本每个接口都有入参校验,所以如果每个方法都使用前面的校验方式,还是稍显复杂。

我们可以通过SpringBoot提供的@RestControllerAdvice@ControllerAdvice 结合@ExceptionHandler使用完成异常统一处理,需要捕获什么异常通过@ExceptionHandler来指定对应异常类就可以了。

@RestControllerAdvice(@ResponseBody+@ControllerAdvice),是一个Controller增强器,可对controller中被@RequestMapping注解的方法加一些逻辑处理。

最常用的就是异常处理,需要配合@ExceptionHandler使用。当将异常抛到controller时,可以对异常进行统一处理,规定返回的json格式或是跳转到一个错误页面。

这里原则是按照从小到大异常进行依次执行。通俗来讲就是当小的异常没有指定捕获时,大的异常包含了此异常就会被执行。比如Exception 异常包含了所有异常类,是所有异常超级父类,当出现没有指定异常时,此时对应捕获了Exception异常的方法会执行。

Java Bean入参校验

在springboot2.3.0以上版本中,MethodArgumentNotValidException extends BindExceptionBindException extends Exception implements BindingResult,在2.3.0以下的版本中MethodArgumentNotValidException extends ExceptionBindException extends Exception implements BindingResult,所以会有form-data入参校验与Json入参校验分开捕获,form-data入参校验与Json入参统一使用bindingresult捕获两种写法。其实这两种都对,大家根据自己的版本来选择合适的写法即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* Bean入参校验
* @param e springboot2.3.0后,MethodArgumentNotValidException extends BindException
* @param request
* @return Response<Void>
*/
@ExceptionHandler(BindException.class)
public Response<Void> handlerBindException(BindException e, HttpServletRequest request) {
String requestUri = request.getRequestURI();
List<String> messageList = e.getBindingResult()
.getFieldErrors()
.stream()
.map(FieldError::getDefaultMessage)
.toList();
String message = String.valueOf(messageList);
log.error("[统一异常处理]请求地址:{}, 参数校验异常:{}", requestUri, message);
return new Response<>(Code.BAD_REQUEST, null, message);
}

单一参数入参校验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* requestParam单参数校验(需要在类上面加校验注解 方法上面加不管用的)
* @param exception ConstraintViolationException extends ValidationException
* @param request
* @return Response<Void>
*/
@ExceptionHandler(ConstraintViolationException.class)
public Response<Void> handlerValidationException(ConstraintViolationException exception, HttpServletRequest request) {
String requestUri = request.getRequestURI();

Set<ConstraintViolation<?>> constraintViolations = exception.getConstraintViolations();
String validateMsg = String.valueOf(constraintViolations.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.toList()));
log.error("[统一异常处理]请求地址:{}, 参数校验异常:{}", requestUri, validateMsg);
return new Response<>(Code.BAD_REQUEST, null, validateMsg);
}

参考链接