1. 复现问题
今天在使用Knife4j
调用后端接口,报出如下错误:
javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint 'javax.validation.constraints.NotBlank' validating type 'java.lang.Long'. Check configuration for 'id'
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.getExceptionForNullValidator(ConstraintTree.java:116)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.getInitializedConstraintValidator(ConstraintTree.java:162)
at org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree.validateConstraints(SimpleConstraintTree.java:54)
at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:75)
at org.hibernate.validator.internal.metadata.core.MetaConstraint.doValidateConstraint(MetaConstraint.java:130)
at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:123)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:555)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:518)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:488)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:450)
at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:400)
at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:172)
at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:109)
at org.springframework.boot.autoconfigure.validation.ValidatorAdapter.validate(ValidatorAdapter.java:65)
at org.springframework.validation.DataBinder.validate(DataBinder.java:895)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.validateIfApplicable(AbstractMessageConverterMethodArgumentResolver.java:245)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:137)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:170)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
......
即javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint 'javax.validation.constraints.NotBlank' validating type 'java.lang.Long'. Check configuration for 'id'
2. 分析问题
正赶上最近ChatGPT
很火,于是借助ChatGPT
来解决我的问题,如下所示:
This means that the constraint “NotBlank” is not valid for a Long type value in the field “id”. A Long type cannot support the NotBlank constraint. You should either remove the NotBlank annotation or use another type such as a String.
芭比Q的是ChatGPT
是英文解释,我们不妨翻译成中文,如下所示:
这意味着约束“NotBlank”对于字段“id”中的长整型类型值无效。Long 类型不能支持 NotBlank 约束。应删除NotBlank注解或使用其他类型(如字符串)。
从中文翻译来看,由于id
的类型是长整型的,而NotBlank
不能修饰长整型,如下是我的代码:
/**
* 自定义组件id
* */
@NotBlank(message = "自定义组件id不能为空")
@ApiModelProperty(name = "id", value = "自定义组件id", required = true, example = "1")
private Long id;
但其给出两个解决方案:
-
删除
NotBlank
注解 -
使用其他数据类型(如字符串)
显然,这两种方式都无法解决我的问题。
因为id
一般都是长整型,因而不能修改其类型,而又不能删除注解,因为必须限制id
不能为空。
id
不能为空,因而,我们可以考虑不能为空
的注解,即@notNull
。
3. 解决问题
既然@NotBlank
注解不能修饰长整型等,而@NotNull
注解可以修饰长整型,因而可以进行如下修改:
/**
* 自定义组件id
* */
@NotNull(message = "自定义组件id不能为空")
@ApiModelProperty(name = "id", value = "自定义组件id", required = true, example = "1")
private Long id;
重新启动服务后调用接口,即可成功访问,如下图所示:
此外,@NotBlank
注解除了不能修饰长整型,也不能修饰浮点型,布尔型等。
因为@NotBlank
注解只能作用在String
上,不能为null
。而且调用trim()
后,长度必须大于0 ("test")
,即必须有实际字符。
4. 重要补充
-
@NotNull
注解-
不能为
null
, -
可以为
empty
,比如""
," "
-
-
@NotEmpty
注解-
不能为
null
-
而且长度必须大于
0
,比如" "
-
只能使用在字符串上
-
5. 其他说明
-
如果你对
Knife4j
比较感兴趣,可以参考这篇博文:全网最全的Knife4j swaggerj介绍 -
如果你对@NotEmpty、@NotBlank等注解感兴趣,可以参考这篇博文:@NotEmpty、@NotBlank等注解的正确使用