0

我在使用 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

我有我的自定义主题,我确信 SIMPLE 主题没有太多修改。我的拦截器堆栈与默认值堆栈几乎相同。

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

我发现可以通过从堆栈中删除 conversionError 拦截器来删除一个字段错误。但我认为这不会导致这个问题。Struts 应该能够显示仅由开发人员定义的错误,对吧?

请帮助我

4

3 回答 3

1

您需要了解Struts2 如何处理转换错误

类型转换期间发生的任何错误可能会或可能不希望被报告。例如,报告输入“abc”无法转换为数字可能很重要。另一方面,报告空字符串“”不能转换为数字可能并不重要——尤其是在难以区分用户未输入值与输入空白值的 Web 环境中。

...

重要的是要知道实际上没有直接报告这些错误。相反,它们被添加到 ActionContext 中名为 conversionErrors 的映射中。然后可以通过多种方式访问​​此地图并相应地报告错误。

报错有两种方式:

  1. 在全局范围内,使用转换错误拦截器
  2. 在每个字段的基础上,使用转换验证器

您正在使用这两种机制,因此会复制发现的错误。正如文档所述,通常您不想报告所有转换错误,因此应该从堆栈中删除ConversionErrorInterceptor 。conversion现在,您可以使用验证器有选择地将转换错误作为字段错误引发。

于 2012-01-26T14:56:40.403 回答
1

我发现我的自定义DateTimeConverter导致了异常和额外的错误消息。因为我从 Struts2 书中找到了以下代码,以更改我的 Date 的正常格式。当它抛出异常时,它会在控制台上显示异常并在字段错误上显示错误消息,而不是将异常传递给验证器。我认为这是一种错误,因为这个类扩展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 全局日期格式吗?谢谢

于 2012-01-27T04:56:08.070 回答
0

我昨天遇到了类似的问题,终于找到了我喜欢分享的解决方案。我在我的操作中使用注释进行验证,所以我更改了默认的 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...
   }
} 
于 2012-05-04T10:00:34.857 回答