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インターセプターを削除することで、1つのフィールドエラーを削除できることがわかりました。しかし、それがこの問題を引き起こすとは思わない。Strutsは、開発者によってのみ定義されたエラーを表示できるはずですよね?

これで私を助けてください

4

3 に答える 3

1

Struts2 が変換エラーを処理する方法を理解する必要があります。

型変換中に発生するエラーは、報告する必要がある場合としない場合があります。たとえば、入力「abc」を数値に変換できなかったことを報告することが重要な場合があります。一方、空の文字列 "" を数値に変換できないことを報告することは重要ではない可能性があります。特に、値を入力していないユーザーと空白の値を入力したユーザーを区別するのが難しい Web 環境では重要ではありません。

...

これらのエラーは実際には直接報告されないことを知っておくことが重要です。むしろ、それらは ActionContext の conversionErrors と呼ばれるマップに追加されます。このマップにアクセスするにはいくつかの方法があり、それに応じてエラーを報告できます。

エラー報告は、次の 2 つの方法で発生する可能性があります。

  1. Conversion Error Interceptor を使用してグローバルに
  2. 変換バリデーターを使用して、フィールドごとに

両方のメカニズムを使用しているため、見つかったエラーが重複しています。ドキュメントに記載されているように、通常、すべての変換エラーを報告する必要はないため、スタックからConversionErrorInterceptorを削除する必要があります。バリデーターを使用して、変換エラーをフィールド エラーとして選択的に発生させることができるようになりましたconversion

于 2012-01-26T14:56:40.403 に答える
1

私のカスタムDateTimeConverterが例外と余分なエラーメッセージを引き起こしていることがわかりました。Date の通常の形式を変更するために、Struts2 の本から以下のコードを見つけたからです。例外をスローすると、例外をバリデーターに渡すのではなく、コンソールに例外を表示し、フィールド エラーにエラー メッセージを表示します。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;
    }
}

}

とにかく、バリデーション XMLに変更throw new TypeConversionException(e);してバリデーターreturn null;を追加しました。REQUIRED日付フィールドに無効な日付を入力すると、エラーが表示されるようになりました。

PS: Struts のグローバルな日付形式を変更する他の方法はありますか? ありがとう

于 2012-01-27T04:56:08.070 に答える
0

昨日同様の問題に直面し、最終的に共有したい解決策を見つけました。検証のためにアクションで注釈を使用しているため、デフォルトの struts インターセプター スタックを変更し、StrutsConversionErrorInterceptor の代わりに SensibleConversionErrorInterceptor を配置しました。これはまったく同じですが、検証エラーは発生しません。代わりに、アクションの注釈で構成された検証によって生成されます。

これが私のコンバーターです:

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 に答える