Могу ли я создать JSF Validator с параметрами, указанными в разметке JSF? - PullRequest
3 голосов
/ 20 января 2012

Например: у меня есть JSF Validator для проверки электронной почты таким образом:

@FacesValidator(value="validateEmail")
public class Email implements Validator
{

private static final String EMAIL_REGEXP =
        "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";

@Override
public void validate(FacesContext context, UIComponent c, Object val) throws ValidatorException
{
    String email = (String) val;
    Pattern mask = null;
    mask = Pattern.compile(EMAIL_REGEXP);
    Matcher matcher = mask.matcher(email);

    if (!matcher.matches()) {
        FacesMessage message = new FacesMessage();
        message.setDetail("Must be of the form xxx@yyy.zzz");
        message.setSummary("E-mail Addresss not valid");
        message.setSeverity(FacesMessage.SEVERITY_ERROR);
        throw new ValidatorException(message);
    }
}
}

Этот валидатор выдаст исключение, если пользователь не введет электронную почту.Однако иногда я хочу сделать электронную почту необязательным полем.Есть ли способ сделать это, не требующий от меня написания другого валидатора?

В идеале я хотел бы, чтобы он проверил наличие параметра где-нибудь в разметке JSF, которая его использует.

1 Ответ

10 голосов
/ 20 января 2012

Чтобы ответить на ваш конкретный вопрос, вы можете использовать <f:attribute>, заключенный в тот же компонент.

<h:inputText>
    <f:validator validatorId="validateEmail" />
    <f:attribute name="foo" value="bar" />
</h:inputText>

Внутри метода validate() он доступен по UIComponent#getAttributes() 2-го UIComponent аргумента.

String foo = component.getAttributes().get("foo"); // bar

Однако лучшее решение в вашем конкретном случае - просто разрешить валидатору return, когда значение равно нулю или пусто.

if (email == null || email.isEmpty()) {
    return;
}

В JSF 1.x в этом нет необходимости, потому что валидаторы не будут вызываться, когда ввод пуст или пуст. Но в JSF 2.x это изменилось, чтобы поддержать проверку бина JSR303. Поэтому, если вы хотите пропустить проверку пустых полей, вам нужно будет проверить это в каждом JSF Validator.

Обратите внимание, что когда у вас есть это в вашем web.xml

<context-param>
    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
    <param-value>true</param-value>
</context-param>

тогда вы можете спокойно пропустить часть email.isEmpty() из проверки, потому что она всегда будет null вместо пустой строки.


Не имеет отношения к конкретной проблеме, шаблон которой у вас там устарел. В эти дни символы юникода разрешены в адресах электронной почты.

private static final String EMAIL_REGEXP = "([^.@]+)(\\.[^.@]+)*@([^.@]+\\.)+([^.@]+)";

(обратите внимание, что ^ и $ не нужны, потому что Pattern уже неявно использует это)

Далее я также предлагаю сделать Pattern#compile() непосредственно для переменной static final. Компиляция шаблона является относительно дорогой, и экземпляр Pattern в любом случае безопасен для потоков.

private static final Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_REGEXP);
...