注解说明
-
@Null
被注释的元素必须为null -
@NotNull
被注释的元素不能为null -
@AssertTrue
被注释的元素必须为true -
@AssertFalse
被注释的元素必须为false -
@Min(value)
被注释的元素必须是一个数字,其值必须大于等于指定的最小值 -
@Max(value)
被注释的元素必须是一个数字,其值必须小于等于指定的最大值 -
@DecimalMin(value)
被注释的元素必须是一个数字,其值必须大于等于指定的最小值 -
@DecimalMax(value)
被注释的元素必须是一个数字,其值必须小于等于指定的最大值 -
@Size(max,min)
被注释的元素的大小必须在指定的范围内(用于校验集合个数)。 -
@Digits(integer,fraction)
被注释的元素必须是一个数字,其值必须在可接受的范围内,integer整数的位数,fraction小数位的进度,fraction=2就是保留两位小数 -
@Past
被注释的元素必须是一个过去的日期 -
@PastOrPresent
被注释的元素必须是一个过去或者现在的日期 -
@Future
被注释的元素必须是一个将来的日期 -
@FutureOrPresent
被注释的元素必须是一个将来或者现在的日期 -
@Pattern(value)
被注释的元素必须符合指定的正则表达式。 -
@Email
被注释的元素必须是电子邮件地址 -
@Length
被注释的字符串的大小必须在指定的范围内 -
@NotEmpty
被注释的字符串必须非空 -
@Range
被注释的元素必须在合适的范围内 -
@NotBlank
字符串,不为空字符串 -
@Positive
数字,正数 -
@PositiveOrZero
数字,正数或0 -
@Negative
数字,负数 -
@NegativeOrZero
数字,负数或0
实体对象
@Data
public class VerifyRuleDTO {
private Long id;
@NotBlank(message = "can not be empty")
private String flowId;
@NotBlank(message = "can not be empty")
private String ruleCode;
@NotBlank(message = "can not be empty")
private String ruleName;
@Max(10)
@Min(5)
private int amt;
// @Pattern(regexp = "desc|asc", message = "排序值无效")
// private String sortOrder = "asc";
}
控制层
@RestController
@RequestMapping("/api/verify/rule/v1")
@Slf4j
public class VerifyRuleController {
@RequestMapping(value = "saveRule", method = RequestMethod.POST)
public AiResponse saveRule(@Valid @RequestBody VerifyRuleDTO verifyRule) {
// ...
return AiResponse.success("insert successful.");
}
}
全局异常控制
@ControllerAdvice
@Slf4j
public class ExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public AiResponse exceptionHandler(Exception ex) {
log.error("exception message[{}]", ex.getMessage());
if (ex instanceof MethodArgumentNotValidException) {
MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) ex;
FieldError fieldError = methodArgumentNotValidException.getBindingResult().getFieldError();
if (fieldError != null) {
// 校验失败的字段名
String fieldName = fieldError.getField();
// 字段校验失败的具体信息
String message = fieldError.getDefaultMessage();
return AiResponse.failed(String.format("%s %s", fieldName, message));
}
return AiResponse.failed(ex.getMessage());
}
return AiResponse.failed(ex.getMessage());
}
}
测试结果
请求体
{
"flowId": "answer",
"ruleCode": "1",
"ruleName": "2",
"amt": 1
}
响应体
{
"code": "0001",
"desc": "failed",
"data": "amt 最小不能小于5"
}
全局异常控制
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public Response handleMethodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException e) {
String message = e.getBindingResult().getFieldErrors().stream().map(ele -> ele.getField() + ele.getDefaultMessage()).collect(Collectors.joining(","));
return Response.failed(ResponseCodeEnum.INVALID_ARGUMENT, message);
}
hibernate的校验模式配置
如果请求存在多个参数都校验失败,则遇到第一个校验失败就抛出异常,接下来的异常参数不做校验
@Configuration
public class ValidatorConfig {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor(@Qualifier("validator") Validator validator) {
MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
// 设置 validator 为快速失败返回
methodValidationPostProcessor.setValidator(validator);
return methodValidationPostProcessor;
}
@Bean
public Validator validator() {
ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
.configure()
// failFast=true: 只要出现校验失败的情况就立即结束校验,不再进行后续的校验
.failFast(true)
.buildValidatorFactory();
return validatorFactory.getValidator();
}
}
Hibernate Validator 6.1.5.Final - Jakarta Bean Validation Reference Implementation: Reference Guide
@Digits使用
class Item {
@Digits(integer = 6, fraction = 2, message = "{javax.validation.constraints.Digits.message}")
private BigDecimal amount;
}
在上面的类中integer并且fraction是强制性的,并且消息是可选参数,@Digit并且我们可以配置自定义错误消息。
现在,我们在源目录中创建一个名为ValidationMessages.properties的属性文件。
javax.validation.constraints.Digits.message = "custom error message will be here"
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
springboot在2.3之后,spring-boot-starter-web的依赖项已经去除了validate依赖
@Data
public class Request<T> {
private String requestId;
private String visitKey;
// SpringBoot针对泛型失效的解决方案
@Valid
private T body;
}
@Slf4j
@ControllerAdvice
@ResponseBody
public class GlobalController {
@ExceptionHandler(MethodArgumentNotValidException.class)
public Response handleBindException(MethodArgumentNotValidException e) {
return Response.failed(ResponseEnum.REQUEST_PARAM_ERROR, e.getBindingResult().getFieldError().getDefaultMessage());
}
}
参考链接
- @Valid和@Validated的总结区分