编写接口时,为防止非法参数对业务造成影响,需要在Controller层添加参数校验。通过javax.validation的一系列注解可以帮助我们完成参数校验,免去繁琐的逻辑判断。
依赖
根据JSR 380规范,validation-api 依赖中包含标准的参数验证API:
Bean Validation 2.0 版本需要Java 8或更高版本。
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.2.Final</version>
</dependency>
Hibernate Validator是参数验证API的具体实现。
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.7.Final</version>
</dependency>
在Spring Boot 2.3.x之前,以上依赖在spring-boot-starter-web 中自动引入。 Spring Boot 2.3.x之后,需要手动引入。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
使用场景
入参为实体对象
当入参为实体对象时,在对象上添加@Validated注解,并且实体属性上添加约束注解(如@Size等) 就能实现参数的自动校验。
- 实体对象添加@Validated注解
public R<Boolean> save(@RequestBody @Validated User user) {}
- 实体属性上添加约束注解。
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.constraints.Email;
public class User {
@NotNull(message = "用户名称不能为空")
private String name;
@AssertTrue
private boolean working;
@Size(min = 6, max = 20, message
= "密码长度必须是6-20个字符")
private String password;
@Min(value = 18, message = "年龄最小不超过18")
@Max(value = 150, message = "年龄最大不超过150")
private int age;
@Email(message = "邮箱格式不正确")
private String email;
}
- 如果不符合验证要求,则将注解属性
message 的信息作为响应提示信息。
{
"code": 400,
"success": true,
"data": null,
"msg": "用户名称不能为空"
}
全局异常拦截
添加参数检验全局拦截处理类
@RestControllerAdvice
@Configuration
public class CommonExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public R<Object> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(","));
return R.fail(ResultCode.PARAM_MISS, message);
}
@ExceptionHandler(BindException.class)
public R<Object> bindExceptionHandler(BindException e) {
String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(","));
return R.fail(ResultCode.PARAM_MISS, message);
}
@ExceptionHandler(ConstraintViolationException.class)
public R constraintViolationExceptionHandler(ConstraintViolationException e) {
String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(","));
return R.fail(ResultCode.PARAM_MISS, message);
}
}
注解
注解 | 支持验证类型 | 说明 |
---|
@Null | 任意类型 | 验证带注解的属性值是null。 | @NotNull | 任意类型 | 验证带注解的属性值不为null。 | @NotEmpty | String、 Collection、 Map或Array | 验证带注解的属性值不为null或空。 | @NotBlank | String | 验证带注解的属性值不为null或空字符,只针对字符串检验。 | @AssertTrue | Boolean | 验证带注解的属性值是true。 | @AssertFalse | Boolean | 验证带注解的属性值是false。 | @Size | String、 Collection、 Map或Array | 验证带注解的属性值的大小介于属性min和max之间。 | @Digits | BigDecimal、BigInteger、CharSequence、byte, short, int, long以及它们的封装类型 | 验证带注解的属性值是可接受范围内的数字。 | @Min | BigDecimal、BigInteger、byte, short, int, long以及它们的封装类型 | 验证带注解的属性值不小于@Min指定的value值。 | @Max | 同@Min要求 | 验证带注解的属性值不大于@Max指定的value值。 | @DecimalMin | 同@Digits要求 | 验证带注解的属性值不小于@DecimalMin指定的value值。 | @DecimalMax | 同@Digits要求 | 验证带注解属性值不大于@DecimalMax指定的value值。 | @Positive | 同@Min要求 | 验证带注解的属性值是正数。 | @PositiveOrZero | 同@Min要求 | 验证带注解的属性值是正数或0。 | @Negative | 同@Min要求 | 验证带注解的属性值是负数。 | @NegativeOrZero | 同@Min要求 | 验证带注解的属性值是负数或0。 | @Past | java.util.Date、java.util.Calendar、java.time | 验证带注解的属性值为过去时间(比当前时间早)。 | @PastOrPresent | 同@Past要求 | 验证带注解的属性值为过去时间(比当前时间早)或当前时间。 | @Future | 同@Past要求 | 验证带注解的属性值为未来时间(比当前时间晚)。 | @FutureOrPresent | 同@Past要求 | 验证带注解的属性值为未来时间(比当前时间晚)或当前时间。 | @Pattern | String | 验证带注解的属性值与指定的正则表达式匹配。 | @Email | String | 验证带注解的属性值是有效的电子邮件地址。 |
个人博客 > 欢迎来访
|