Повторное использование валидатора пользовательских выражений в Struts 2

В Struts 2 мы можем разработать @CustomValidator, который можно использовать во всем приложении.

@CustomValidator(type = "CustomerNumberValidator", fieldName = "customerNo")

Для проверки большего поля мы используем @ExpressionValidator

@ExpressionValidator(expression = 
"( (!''.equals(account.firstName) && (!''.equals(account.lastName) )
   || (presonalAccount == false)", 
   key = "validate.account.name")

Если выражение слишком сложное и должно работать с более более чем одним полем, мы используем OGNL для вызова статического метода. Статический метод выполнит проверку и вернет, например, boolean

@ExpressionValidator(expression = "@foo.bar.CalendarUtil@compareDates(fromDate,toDate)", key = "validate.date.before")

Выше показано, как работает Пользовательский валидатор выражений!

И мы используем @foo.bar.CalendarUtil@compareDates во всем приложении, чтобы сделать эту проверку для нас.

Есть ли другой подход, который позволяет нам использовать собственный широкий валидатор?!

Есть ли какой-либо пользовательский валидатор выражений, который можно добавить в Struts, и мы можем вызвать его в Action так же, как мы используем @CustomValidator?


person Alireza Fattahi    schedule 20.01.2015    source источник


Ответы (2)


Создайте пользовательский валидатор (не связанный с полем):

public final class CompareDatesValidator extends ValidatorSupport {
    private String fromDate; // getter and setter
    private String toDate;   // getter and setter    

    @Override
    public void validate(Object o) throws ValidationException {
        Date d1 = (Date)parse(fromDate, Date.class);
        Date d2 = (Date)parse(toDate, Date.class);

        if (d1==null || d2==null || d2.before(d1)){
            addActionError(getDefaultMessage());
        }
    }
}

Зарегистрируйте пользовательский валидатор в файле validators.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
     "-//OpenSymphony Group//XWork Validator Config 1.0//EN"
     "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd">
<validators>
    <validator name="compareDatesValidator" 
              class="org.foo.bar.CompareDatesValidator"/>
</validators>

Используйте валидатор в действии:

private Date startDate; // getter and setter
private Date endDate;   // getter and setter

@Validations(
    customValidators={
        @CustomValidator(type="compareDatesValidator", 
            message="Dates provided are not valid."
            parameters={
                @ValidationParameter(name="fromDate", value="${startDate}"), 
                @ValidationParameter(name="toDate",   value="${endDate}")})})
public String execute(){
    return SUCCESS;
}
person Andrea Ligios    schedule 20.01.2015
comment
Отлично, именно то, что я искал, не могли бы вы обновить свой ответ и сообщить мне в приложении i18n, как я могу прочитать пользовательский ключ сообщения в compareDatesValidator и установить его в addActionError - person Alireza Fattahi; 20.01.2015
comment
Мне кажется, это еще один вопрос, поэтому было бы лучше опубликовать его как еще один вопрос (например, как получать сообщения i18n из пользовательского валидатора)... - person Andrea Ligios; 20.01.2015
comment
Ну, я спросил об этом по адресу: stackoverflow.com/questions/28054378/ - person Alireza Fattahi; 20.01.2015

Вы можете использовать пользовательский валидатор без поля, если вам нужно проверить несколько полей. Пользовательский валидатор, не являющийся полем, должен расширять ValidatorSupport и реализовывать метод validate. Затем примените собственный валидатор в -validation.xml или используйте аннотацию @CustomValidator. Там вы можете добавить пользовательские выражения как @ValidationParameter и анализировать их при проверке.

Примечание.

Этот метод я использовал вначале в этом ответе:

public class RetypeValidator extends ValidatorSupport {

  private String value = null;

  public String getValue() {
    return value;
  }
  public void setValue(String value) {
    this.value = value;
  }

  private String retypeValue = null;

  public String getRetypeValue() {
    return retypeValue;
  }

  public void setRetypeValue(String value) {
    retypeValue = value;
  }

  @Override
  public void validate(Object object) throws ValidationException {
    String value = (String) parse(this.value, String.class);
    String retypeValue = (String) parse(this.retypeValue, String.class);
    if (value != null && retypeValue != null && !value.equals(retypeValue))
      addActionError(getDefaultMessage());
  }
}

Другой вариант — переопределить метод validate класса ActionSupport. Вызов этого метода контролируется через validation перехватчик. Этот метод проверки называется программным и используется по умолчанию независимо от валидаторов, применяемых во время декларативной проверки.

person Roman C    schedule 20.01.2015