Hibernatevalidation器:@Email接受ask @ stackoverflow为有效的?

我正在使用@Email注释来validation电子邮件地址。 我遇到的问题是它接受诸如ask@stackoverflow作为有效的电子邮件地址的东西。 我想这是因为他们想要支持Intranet地址,但我似乎无法find一个标志,所以它不检查扩展名。

我是否真的需要切换到@Pattern (以及任何对灵活的电子邮件模式的build议),还是我错过了一些东西?

实际上,Hibernate Validator的@Email在内部使用regexp 。 你可以很容易地根据这个正则expression式来定义你自己的约束,根据需要进行修改(注意DOMAIN末尾的+ ):

 @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = {}) @Pattern(regexp = Constants.PATTERN, flags = Pattern.Flag.CASE_INSENSITIVE) public @interface EmailWithTld { String message() default "Wrong email"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; } interface Constants { static final String ATOM = "[a-z0-9!#$%&'*+/=?^_`{|}~-]"; static final String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)+"; static final String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]"; static final String PATTERN = "^" + ATOM + "+(\\." + ATOM + "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$"; } 

您也可以使用约束组合作为解决方法。 在下面的示例中,我依靠@Emailvalidation器来执行主validation,并添加@Patternvalidation器以确保地址的格式为x@yz (我不build议仅使用@Pattern以下代码定期电子邮件validation

 @Email(message="Please provide a valid email address") @Pattern(regexp=".+@.+\\..+", message="Please provide a valid email address") @Target( { METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Constraint(validatedBy = {}) @Documented public @interface ExtendedEmailValidator { String message() default "Please provide a valid email address"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } 

实际validation电子邮件地址是非常复杂的。 无法validation电子邮件地址在语法上是否正确,并且在注释中处理预期的收件人。 @Email注释是一个有用的最小检查,不会受到漏报的问题。

validation的下一步应该是发送一个电子邮件,用户必须完成一个挑战,以确定用户可以访问电子邮件地址。

在步骤1中接受一些误报并允许一些无效的电子邮件地址通过比拒绝有效的用户更好。 如果你想申请额外的规则,你可以添加更多的支票,但要认真对待你认为是有效的电子邮件地址的要求。 例如,RFC中没有任何规定i@nl将是无效的,因为nl是已注册的国家顶级域名。

这是一个使用Apache Commons Validator的javax.validation电子邮件validation器

 public class CommonsEmailValidator implements ConstraintValidator<Email, String> { private static final boolean ALLOW_LOCAL = false; private EmailValidator realValidator = EmailValidator.getInstance(ALLOW_LOCAL); @Override public void initialize(Email email) { } @Override public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) { if( s == null ) return true; return realValidator.isValid(s); } } 

而注释:

 @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = {CommonsEmailValidator.class}) @Documented @ReportAsSingleViolation public @interface Email { String message() default "{org.hibernate.validator.constraints.Email.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface List { Email[] value(); } } 

约束组合解决scheme不起作用。 当Email与Pattern结合使用时,Email正则expression式的优先级更高。 我相信这是因为电子邮件注释覆盖了几个模式属性,即标志和正则expression式(在这里的关键之一)如果我删除@Email ,那么只有这样@Pattern正则expression式适用于validation。

 /** * @return an additional regular expression the annotated string must match. The default is any string ('.*') */ @OverridesAttribute(constraint = Pattern.class, name = "regexp") String regexp() default ".*"; /** * @return used in combination with {@link #regexp()} in order to specify a regular expression option */ @OverridesAttribute(constraint = Pattern.class, name = "flags") Pattern.Flag[] flags() default { }; 

显然我对党迟到了,我还在回答这个问题,

为什么不能在我们的Validation类中使用正则expression式来使用@Pattern注解

 public Class Sigunup { @NotNull @NotEmpty @Pattern((regexp="[A-Za-z0-9._%-+]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}") private String email; } 

它更容易。