Struts2 проверяет 3 раза в одном текстовом поле - PullRequest
0 голосов
/ 26 января 2012

У меня действительно огорчает проблема со Struts (2.2.3).Вот мои проверки полей в ActionName-validation.xml

<field name="txtRequestDateFrom">
   <field-validator type="conversion">
      <param name="repopulateField">false</param>
      <message>${getText("E011", {"Date from"})}</message>
   </field-validator>
</field>

У меня нет метода validate () в моем классе действий.И у меня есть это в моем классе действий:

private Date txtRequestDateFrom;
{getter, setters}

Когда я ввожу буквы в поле txtRequestDateFrom, я получаю 3 сообщения проверки на

<s:fielderror fieldName="txtRequestDateFrom"/> 

Это выглядит так

Invalid field value for field "txtRequestDateFrom".
Invalid field value for field "txtRequestDateFrom".
Date from has an invalid value

У меня есть своя собственная тема, и я уверен, что не будет никаких особых изменений от простой темы.Мой стек перехватчиков во многом аналогичен стеку значений по умолчанию.

<interceptor-stack name="defaultStack">
        <interceptor-ref name="security"/>
            <interceptor-ref name="exception"/>
            <interceptor-ref name="alias"/>
            <interceptor-ref name="servletConfig"/>
            <interceptor-ref name="i18n"/>
            <interceptor-ref name="prepare"/>
            <interceptor-ref name="chain"/>
            <interceptor-ref name="debugging"/>
            <interceptor-ref name="scopedModelDriven"/>
            <interceptor-ref name="modelDriven"/>
            <interceptor-ref name="fileUploadStack" />
            <interceptor-ref name="fileUpload" >
            <param name="maximumSize">4000000</param>
        </interceptor-ref> 
            <interceptor-ref name="checkbox"/>
            <interceptor-ref name="multiselect"/>
            <interceptor-ref name="staticParams"/>
            <interceptor-ref name="actionMappingParams"/>                   
        <interceptor-ref name="params"/>
        <interceptor-ref name="conversionError" />
        <interceptor-ref name="validation">
            <param name="excludeMethods">execute, complete ...</param>
        </interceptor-ref>
        <interceptor-ref name="workflow"/>

    </interceptor-stack>

Я обнаружил, что одну ошибку поля можно удалить, удалив перехватчик converError из стека.Но я не думаю, что это вызовет эту проблему.Struts должен отображать ошибки, определенные только разработчиком, верно?

Пожалуйста, помогите мне в этом

Ответы [ 3 ]

1 голос
/ 27 января 2012

Я обнаружил, что мой пользовательский DateTimeConverter вызывает исключения и дополнительное сообщение об ошибке.Потому что я нашел код ниже из книги Struts2, чтобы изменить обычный формат моей даты.Когда он генерирует исключение, он показывает исключение на консоли и сообщение об ошибке в поле error, а не передает исключение в валидатор.Я думаю, что это своего рода ошибка, потому что этот класс расширяет StrutsTypeConverter, и он должен работать как обычные конвертеры.

public class StringToDateTimeConverter extends StrutsTypeConverter {

private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd");

public Object convertFromString(Map context, String[] strings, Class toClass) {     
    if (strings == null || strings.length == 0 || strings[0].trim().length() == 0) {
        return null;
    }

    try {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DATETIME_FORMAT.parse(strings[0]));
        calendar.set(Calendar.HOUR, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();

    } catch (ParseException e) {
        throw new TypeConversionException(e);
    }
}

public String convertToString(Map context, Object date) {
    if (date != null && date instanceof Date) {
        return DATETIME_FORMAT.format(date);
    } else {
        return null;
    }
}

}

В любом случае я изменил throw new TypeConversionException(e); на return null; и добавил REQUIRED валидатор при проверке XML.Теперь он показывает ошибку, когда я ставлю недопустимую дату в свои поля даты.

PS: Есть ли другой способ изменить глобальный формат даты Struts?Спасибо

1 голос
/ 26 января 2012

Вам необходимо понять , как Struts2 обрабатывает ошибки преобразования .

Любая ошибка, возникающая во время преобразования типа, может быть, а может и не пожелаться, сообщаться. Например, сообщение о том, что ввод «abc» не может быть преобразован в число, может быть важным. С другой стороны, сообщение о том, что пустая строка «» не может быть преобразована в число, может быть неважным, особенно в веб-среде, где сложно отличить пользователя, не вводящего значение, от ввода пустого значения.

...

Важно знать, что ни одна из этих ошибок фактически не сообщается напрямую. Скорее, они добавляются в карту с именем ConversionErrors в ActionContext. Есть несколько способов получить доступ к этой карте и сообщить об ошибках соответственно.

Существует два способа сообщения об ошибках:

  1. В глобальном масштабе с использованием перехватчика ошибок преобразования
  2. Для каждого поля с использованием средства проверки преобразования

Вы используете оба механизма, таким образом дублируя найденные ошибки. Как говорится в документации, обычно вы не хотите сообщать обо всех ошибках преобразования и, следовательно, должны удалять ConversionErrorInterceptor из стека. Теперь вы можете выборочно выдавать ошибки преобразования как полевые ошибки, используя валидатор conversion.

0 голосов
/ 04 мая 2012

Вчера я столкнулся с подобной проблемой и, наконец, нашел решение, которым хотел бы поделиться. Я использую аннотации в своих действиях для проверки, поэтому я изменил стек перехватчиков по умолчанию в Struts и поместил свой SensibleConversionErrorInterceptor вместо StrutsConversionErrorInterceptor. Этот код идентичен, но не вызывает ошибок проверки. Вместо этого они генерируются проверкой, настроенной в аннотациях в моих действиях.

Вот мой конвертер:

public class SensibleConversionErrorInterceptor extends StrutsConversionErrorInterceptor {

   private static final long serialVersionUID = 8186282792289268544L;

   @Override
   public String intercept(ActionInvocation invocation) throws Exception {

      ActionContext invocationContext = invocation.getInvocationContext();
      Map<String, Object> conversionErrors = invocationContext.getConversionErrors();
      ValueStack stack = invocationContext.getValueStack();

      HashMap<Object, Object> fakie = null;

      for (Map.Entry<String, Object> entry : conversionErrors.entrySet()) {
         String propertyName = entry.getKey();
         Object value = entry.getValue();

         if (shouldAddError(propertyName, value)) {
            // removed cause error messages are generated from annotations in actions
            // String message = XWorkConverter.getConversionErrorMessage(propertyName, stack);
            // Object action = invocation.getAction();
            // if (action instanceof ValidationAware) {
            //    ValidationAware va = (ValidationAware) action;
            //    va.addFieldError(propertyName, message);
            // }

            if (fakie == null) {
               fakie = new HashMap<Object, Object>();
            }

            fakie.put(propertyName, getOverrideExpr(invocation, value));
         }
      }

      if (fakie != null) {
         // if there were some errors, put the original (fake) values in place right before the result
         stack.getContext().put(ORIGINAL_PROPERTY_OVERRIDE, fakie);
         invocation.addPreResultListener(new PreResultListener() {
            public void beforeResult(ActionInvocation invocation, String resultCode) {
               Map<Object, Object> fakie = (Map<Object, Object>) invocation.getInvocationContext().get(ORIGINAL_PROPERTY_OVERRIDE);
               if (fakie != null) {
                  invocation.getStack().setExprOverrides(fakie);
               }
            }
        });
     }
     return invocation.invoke();
  }

}

И пример действия:

@Conversion
public class ProductAction extends ActionSupport {

   private Product product;
   // getter, setter and so on...

   @Action(...)
   @Validations(
       requiredFields = {
           @RequiredFieldValidator(
               type = ValidatorType.FIELD,
               fieldName = "product.validFrom",
               message = "required.product.validFrom",
               shortCircuit = true
           )
       },
       conversionErrorFields = {
          @ConversionErrorFieldValidator(
              fieldName = "product.validFrom",
              key = "invalid.fieldvalue.product.validFrom'",
              shortCircuit = true
          ) 
       }
   )
   public String saveOrUpdate() {
      // do something here...
   }
} 
...