Domanda

Sto usando l'annotazione @Email per convalidare un indirizzo di posta elettronica. Il problema che sto avendo è che si tratta di accettare le cose come ask@stackoverflow come un indirizzo e-mail valido. Credo che questo è perché vogliono indirizzi supporto Intranet, ma io non riesco a trovare una bandiera in modo che fa controllo per un estensione.

Ho davvero bisogno di passare a @Pattern (e le eventuali raccomandazioni per un modello di e-mail che è flessibile) o mi sto perdendo qualcosa?

È stato utile?

Soluzione

In realtà, @Email da Hibernate Validator uses regExp internamente . Si può facilmente definire il proprio vincolo sulla base di tale regexp, modificato come avete bisogno (notare il + alla fine del 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
                    + ")$";
}

Altri suggerimenti

È inoltre possibile utilizzare vincolo composizione come work-around. Nell'esempio che segue, mi baso sul validatore @Email di fare la convalida principale, e aggiungere un validatore @Pattern per assicurarsi che l'indirizzo è nella forma di x@y.z (Non consiglio utilizzando solo il @Pattern sotto per regolare la convalida e-mail)

@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 {};
}

In realtà la validazione indirizzi e-mail è davvero complesso. Non è possibile convalidare che un indirizzo e-mail è sia sintatticamente corretta e indirizzi il destinatario in un'annotazione. L'annotazione @Email è un utile verifica minima che non soffre il problema di falsi negativi.

Il passo successivo nella convalida dovrebbe essere l'invio di una e-mail con una sfida che l'utente deve completare per stabilire che l'utente ha accesso all'indirizzo e-mail.

E 'meglio essere accettano un paio di falsi positivi al punto 1 e consentire ad alcuni indirizzi e-mail non validi il passaggio di respingere gli utenti validi. Se si desidera applicare regole aggiuntive è possibile aggiungere più controlli, ma essere molto attenti a ciò che si assume essere un requisito di un indirizzo e-mail valido. Per esempio non v'è nulla nelle RFC che impone che i@nl sarebbero validi, perché nl è un dominio di paese di primo livello registrato.

Ecco un validatore javax.validation e-mail usando Apache Commons Validator

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);
    }
}

E l'annotazione:

@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();
    }
}

Ovviamente sono in ritardo alla festa, Still I rispondo a questa domanda,

Perchè non usiamo annotazione @Pattern con le espressioni regolari nella nostra classe di convalida come questo

public Class Sigunup {

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

}

La sua più facile.

La soluzione composizione vincolo non funziona. Quando mail viene utilizzato in combinazione con il modello, la regex mail è tenuto in precedenza maggiore. Credo che questo sia perché l'annotazione Email sovrascrive alcuni attributi del modello, vale a dire bandiere e regexp (la chiave di uno qui) Se rimuovo @Email, solo allora l'espressione regolare @Pattern applicare in convalide.

/**
 * @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 { };

È possibile utilizzare Email regexp, anche fare in modo che la convalida non manca quando l'email è vuota.

@Email(regexp = ".+@.+\\..+|")
@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface ExtendedEmail {

  @OverridesAttribute(constraint = Email.class, name = "message")
  String message() default "{javax.validation.constraints.Email.message}";

  @OverridesAttribute(constraint = Email.class, name = "groups")
  Class<?>[] groups() default {};

  @OverridesAttribute(constraint = Email.class, name = "payload")
  Class<? extends Payload>[] payload() default {};
}

Se avete intenzione di provare la soluzione sopra https://stackoverflow.com/a/12515543/258544 add il @ReportAsSingleViolation nel defination annotazione, in questo modo si evita entrambi messaggio di convalida (uno da @Email e uno da @Pattern) in quanto è un'annotazione composta:

    @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
    @ReportAsSingleViolation

Da @interface ReportAsSingleViolation javax.validation: validazione-api: 1.1.0.Final) Definizione della nota: " ... La valutazione di vincoli composti si ferma sulla prima convalida errore nel caso in cui il vincolo comporre è annotata con ReportAsSingleViolation "

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top