扩展 Hibernate Validator 约束的问题
Problems extending a Hibernate Validator constraint
我正在尝试通过创建一个名为 @NotBlankUri
.
的自定义约束来扩展 @NotBlank
constraint 的行为以应用于 URI
s
这是我的约束注释:
@Target({ METHOD, FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = NotBlankUriValidator.class)
public @interface NotBlankUri {
String message() default "{project.model.NotBlankUri.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
这里是 ConstraintValidator
:
public class NotBlankUriValidator implements ConstraintValidator<NotBlankUri, URI> {
public void initialize(NotBlankUri annotation) {
}
public boolean isValid(URI uri, ConstraintValidatorContext context) {
NotBlankValidator nbv = new NotBlankValidator();
return nbv.isValid(uri.toString(), context);
}
}
问题是 ConstraintValidator
上的 isValid()
方法正在为 URI
参数获取 null
值。我认为这不应该发生,因为 @NotBlank
本身 is annotated @NotNull
。事实并非如此,我尝试将 @NotNull
作为元注释添加到我的 @NotBlankUri
,但这也没有达到预期的效果。我怎样才能让我的注释约束表现得像 @NotBlank
,它似乎叠加在 @NotNull
的行为之上?
根据文档,您不能对非字符串的数据类型使用 @NotBlank
注释。
public @interface NotBlank
Validate that the annotated string is not null or empty. The difference to NotEmpty is that trailing whitespaces are getting ignored.
所以如果你声明你的验证器来验证一个字符串,一切都会好起来的,你可以这样写你的注释:
@Target({ METHOD, FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = NotBlankUriValidator.class)
@NotBlank
public @interface NotBlankUri {
String message() default "{project.model.NotBlankUri.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
如果您对使用 URI class 1 不满意,您需要像这样自己执行自定义验证逻辑:
注解:
@NotNull(message="URI must not be null")
@Target({ METHOD, FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = NotBlankUriValidator.class)
public @interface NotBlankUri {
String message() default "URI must not be blank";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
验证者:
public class NotBlankUriValidator implements ConstraintValidator<NotBlankUri, URI> {
public void initialize(NotBlankUri annotation) {
}
public boolean isValid(URI uri, ConstraintValidatorContext context) {
boolean isValid = true;
System.out.println("URI: " + uri);
//Leave null checks to your @NotNull constraint.
//This is only here to prevent a NullPointerException on the next check.
if(uri == null){
return true;
}
if(uri.toString().isEmpty()){
isValid = false;
}
return isValid;
}
}
我运行以上带测试线束:
public class UriContainer {
public UriContainer(URI uri){
this.uri = uri;
}
@NotBlankUri
private URI uri;
public URI getUri() {
return uri;
}
}
public static void main(String[] args) throws URISyntaxException{
UriContainer filledContainer = new UriContainer(new URI("Stuff"));
UriContainer emptyContainer = new UriContainer(new URI(""));
UriContainer nullContainer = new UriContainer(null);
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<UriContainer>> filledViolations = validator
.validate(filledContainer);
Set<ConstraintViolation<UriContainer>> emptyViolations = validator
.validate(emptyContainer);
Set<ConstraintViolation<UriContainer>> nullViolations = validator
.validate(nullContainer);
System.out.println("Filled: ");
filledViolations.stream().forEach(System.out::println);
System.out.println("Empty: ");
emptyViolations.stream().forEach(System.out::println);
System.out.println("Null: ");
nullViolations.stream().forEach(System.out::println);
}
输出以下违规行为:
URI: Stuff
URI:
URI: null
Filled:
Empty:
ConstraintViolationImpl{interpolatedMessage='URI must not be blank', propertyPath=uri, rootBeanClass=class sandbox.UriContainer, messageTemplate='URI must not be blank'}
Null:
ConstraintViolationImpl{interpolatedMessage='URI must not be null', propertyPath=uri, rootBeanClass=class sandbox.UriContainer, messageTemplate='URI must not be null'}
如您所见,这允许您根据 URI 为空还是空输出不同的错误消息。只需确保如果您使用的是 javax.validation
注释,则检查您操作的数据类型。
1:顺便说一句,它在构造对象时执行验证,如果传递给构造函数的字符串违反 RFC 2396[,则会抛出 URISyntaxException
=19=]
我正在尝试通过创建一个名为 @NotBlankUri
.
@NotBlank
constraint 的行为以应用于 URI
s
这是我的约束注释:
@Target({ METHOD, FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = NotBlankUriValidator.class)
public @interface NotBlankUri {
String message() default "{project.model.NotBlankUri.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
这里是 ConstraintValidator
:
public class NotBlankUriValidator implements ConstraintValidator<NotBlankUri, URI> {
public void initialize(NotBlankUri annotation) {
}
public boolean isValid(URI uri, ConstraintValidatorContext context) {
NotBlankValidator nbv = new NotBlankValidator();
return nbv.isValid(uri.toString(), context);
}
}
问题是 ConstraintValidator
上的 isValid()
方法正在为 URI
参数获取 null
值。我认为这不应该发生,因为 @NotBlank
本身 is annotated @NotNull
。事实并非如此,我尝试将 @NotNull
作为元注释添加到我的 @NotBlankUri
,但这也没有达到预期的效果。我怎样才能让我的注释约束表现得像 @NotBlank
,它似乎叠加在 @NotNull
的行为之上?
根据文档,您不能对非字符串的数据类型使用 @NotBlank
注释。
public @interface NotBlank
Validate that the annotated string is not null or empty. The difference to NotEmpty is that trailing whitespaces are getting ignored.
所以如果你声明你的验证器来验证一个字符串,一切都会好起来的,你可以这样写你的注释:
@Target({ METHOD, FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = NotBlankUriValidator.class)
@NotBlank
public @interface NotBlankUri {
String message() default "{project.model.NotBlankUri.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
如果您对使用 URI class 1 不满意,您需要像这样自己执行自定义验证逻辑:
注解:
@NotNull(message="URI must not be null")
@Target({ METHOD, FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = NotBlankUriValidator.class)
public @interface NotBlankUri {
String message() default "URI must not be blank";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
验证者:
public class NotBlankUriValidator implements ConstraintValidator<NotBlankUri, URI> {
public void initialize(NotBlankUri annotation) {
}
public boolean isValid(URI uri, ConstraintValidatorContext context) {
boolean isValid = true;
System.out.println("URI: " + uri);
//Leave null checks to your @NotNull constraint.
//This is only here to prevent a NullPointerException on the next check.
if(uri == null){
return true;
}
if(uri.toString().isEmpty()){
isValid = false;
}
return isValid;
}
}
我运行以上带测试线束:
public class UriContainer {
public UriContainer(URI uri){
this.uri = uri;
}
@NotBlankUri
private URI uri;
public URI getUri() {
return uri;
}
}
public static void main(String[] args) throws URISyntaxException{
UriContainer filledContainer = new UriContainer(new URI("Stuff"));
UriContainer emptyContainer = new UriContainer(new URI(""));
UriContainer nullContainer = new UriContainer(null);
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<UriContainer>> filledViolations = validator
.validate(filledContainer);
Set<ConstraintViolation<UriContainer>> emptyViolations = validator
.validate(emptyContainer);
Set<ConstraintViolation<UriContainer>> nullViolations = validator
.validate(nullContainer);
System.out.println("Filled: ");
filledViolations.stream().forEach(System.out::println);
System.out.println("Empty: ");
emptyViolations.stream().forEach(System.out::println);
System.out.println("Null: ");
nullViolations.stream().forEach(System.out::println);
}
输出以下违规行为:
URI: Stuff
URI:
URI: null
Filled:
Empty:
ConstraintViolationImpl{interpolatedMessage='URI must not be blank', propertyPath=uri, rootBeanClass=class sandbox.UriContainer, messageTemplate='URI must not be blank'}
Null:
ConstraintViolationImpl{interpolatedMessage='URI must not be null', propertyPath=uri, rootBeanClass=class sandbox.UriContainer, messageTemplate='URI must not be null'}
如您所见,这允许您根据 URI 为空还是空输出不同的错误消息。只需确保如果您使用的是 javax.validation
注释,则检查您操作的数据类型。
1:顺便说一句,它在构造对象时执行验证,如果传递给构造函数的字符串违反 RFC 2396[,则会抛出 URISyntaxException
=19=]