我正在尝试通过创建名为URI
的自定义约束来扩展@NotBlank
constraint的行为以应用于@NotBlankUri
。
这是我的约束注释:
@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);
}
}
问题是isValid()
上的ConstraintValidator
方法获得了null
参数的URI
值。我认为这不应该发生,因为@NotBlank
本身is annotated @NotNull
。不是这样,我尝试将@NotNull
添加为我的@NotBlankUri
的元注释,但这也没有达到预期的效果。如何使我的注释约束表现得像@NotBlank
,它似乎堆叠在@NotNull
的行为之上?
答案 0 :(得分:1)
根据文档,您不能对不是String的数据类型使用@NotBlank
注释。
public @interface NotBlank
验证带注释的字符串不为null或为空。与NotEmpty的区别在于尾随空格被忽略。
因此,如果您声明验证器验证字符串,一切都会好的,您可以像这样编写注释:
@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类 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:东西
URI:
URI:null
填写:
空:
ConstraintViolationImpl {interpolatedMessage ='URI不能为空',propertyPath = uri,rootBeanClass = class sandbox.UriContainer,messageTemplate ='URI不能为空'}
空:
ConstraintViolationImpl {interpolatedMessage ='URI不能为null',propertyPath = uri,rootBeanClass = class sandbox.UriContainer,messageTemplate ='URI不能为null'}
如您所见,这允许您根据URI是空白还是空来输出不同的错误消息。只需确保使用javax.validation
注释,检查您操作的数据类型。
1:顺便说一句,在构造对象时执行验证,如果传递给构造函数的String违反RFC 2396
,则抛出URISyntaxException