6

ModelDriven<Transporter>クエリ文字列を介して実装するアクション クラスにいくつかのパラメーターを渡しています。

<s:form namespace="/admin_side" action="Test" id="dataForm" name="dataForm">
    <s:url id="editURL" action="EditTest" escapeAmp="false">
        <s:param name="transporterId" value="1"/>
        <s:param name="transporterName" value="'DHL'"/>
    </s:url>
    <s:a href="%{editURL}">Click</s:a>
</s:form>

アクション クラスは次のとおりです。

@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value = "struts-default")
public final class TestAction extends ActionSupport 
                           implements Serializable, Preparable, ModelDriven<Transporter>
{
    private static final long serialVersionUID = 1L;
    private Transporter transporter = new Transporter();

    @Action(value = "Test",
    results = {
        @Result(name = ActionSupport.SUCCESS, location = "Test.jsp"),
        @Result(name = ActionSupport.INPUT, location = "Test.jsp")},
    interceptorRefs = {
        @InterceptorRef(value = "paramsPrepareParamsStack", 
                 params = {"params.acceptParamNames", "transporterId, transporterName"})})
    public String load() throws Exception {
        return ActionSupport.SUCCESS;
    }

    @Action(value = "EditTest",
    results = {
        @Result(name = ActionSupport.SUCCESS, location = "Test.jsp"),
        @Result(name = ActionSupport.INPUT, location = "Test.jsp")},
    interceptorRefs = {
        @InterceptorRef(value = "paramsPrepareParamsStack", 
                 params = {"params.acceptParamNames", "transporterId, transporterName"})})
    public String edit() {
        System.out.println(transporter.getTransporterId() 
                         + " : " + transporter.getTransporterName());
        return ActionSupport.SUCCESS;
    }

    @Override
    public Transporter getModel() {
        return transporter;
    }

    @Override
    public void prepare() throws Exception {}
}

サーバー端末に次のメッセージが表示されます。

Jan 09, 2014 4:06:32 PM com.opensymphony.xwork2.interceptor.ParametersInterceptor error
SEVERE: Developer Notification (set struts.devMode to false to disable this message):
Unexpected Exception caught setting 'transporterId' on 'class actions.TestAction: Error setting expression 'transporterId' with value ['1', ]
Jan 09, 2014 4:06:32 PM com.opensymphony.xwork2.interceptor.ParametersInterceptor error
SEVERE: Developer Notification (set struts.devMode to false to disable this message):
Unexpected Exception caught setting 'transporterName' on 'class actions.TestAction: Error setting expression 'transporterName' with value ['DHL', ]

ログ レベルは ですがSEVERE、これらのパラメーターの値はアクション クラスで次のように使用できます。

System.out.println(transporter.getTransporterId() 
                 + " : " + transporter.getTransporterName());

edit()メソッドで。

paramsPrepareParamsStackを then に置き換えると、defaultStackこれらのメッセージは消えます。

のような式['DHL', ]は配列を示します。ただし、モデル内の と は、タイプtransporterIdおよびそれぞれです。transporterNameLongString

私は何を間違っていますか?

4

2 に答える 2

6

ここでは配列の問題は関係ありません (そのように見えても): この種の例外は、Struts がパラメーターの Setter を見つけられないことを意味します。

ParametersInterceptor のドキュメントから:

パラメータの欠落に関する警告

指定されたパラメーター名のセッターがない場合、次のような警告メッセージが devMode に記録されます。

SEVERE: Developer Notification (set struts.devMode to false to disable this 
message):
Unexpected Exception caught setting 'search' on 'class demo.ItemSearchAction: 
Error setting expression 'search' with value ['search', ]
Error setting expression 'search' with value ['search', ] - [unknown location] 
  at com.opensymphony.xwork2.ognl.OgnlValueStack.handleRuntimeException(OgnlValueStack.java:201)
  at com.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:178)
  at com.opensymphony.xwork2.ognl.OgnlValueStack.setParameter(OgnlValueStack.java:152)

したがって、開発者がパラメーター名またはセッターのいずれかで欠落しているセッターまたはタイプミスを見つけることができるようにすることが期待される動作です。

アクションに存在しない要素を JSP に配置することで、このエラーを簡単に再現できます。

あなたのプロパティは(セッターとともに)モデルに存在し、 and を使用ModelDrivenしているparamsPrepareParamsStackので、私が思っていることは次のとおりです。

  • ModelDriven InterceptorModel オブジェクトの処理を委任されています。
  • を初めて呼び出したときはParameters InterceptorModelDriven Interceptorまだ実行されていません。
  • 次に、アクションはモデルオブジェクトについて何も知らず、モデルではなくアクションでパラメーターのセッターを見つけようとします。
  • 代わりに、2 番目のインターセプターが ModelDriven インターセプターの後に実行され、パラメーターを設定する場所を正確に認識します。これが、Action メソッドでパラメーターが正しく設定されている理由です。

しかし、これが当てはまる場合、メソッドでこれらのパラメーターを取得することはできませんprepare()(これが、このスタックを使用している理由です...):
試して、結果をここに投稿してください。

この問題を解決するために最初に頭に浮かぶのは、最初のもののModelDriven Interceptor前に配置Parameters Interceptorすることです(コピーするか、移動することにより、どちらの種類の副作用が発生するかはわかりません)再試行してここに報告する必要があります)。

次に、次のスタックを定義して使用します。

<interceptor-stack name="modelParamsPrepareParamsStack">
    <interceptor-ref name="exception"/>
    <interceptor-ref name="alias"/>
    <interceptor-ref name="i18n"/>
    <interceptor-ref name="checkbox"/>
    <interceptor-ref name="multiselect"/>

    <!-- NEW ModelDriven Position -->
    <interceptor-ref name="modelDriven"/>

    <interceptor-ref name="params">
        <param name="excludeParams">^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param>
    </interceptor-ref>
    <interceptor-ref name="servletConfig"/>
    <interceptor-ref name="prepare"/>
    <interceptor-ref name="chain"/>

    <!-- OLD ModelDriven Position -->
    <!--interceptor-ref name="modelDriven"/-->

    <interceptor-ref name="fileUpload"/>
    <interceptor-ref name="staticParams"/>
    <interceptor-ref name="actionMappingParams"/>
    <interceptor-ref name="params">
        <param name="excludeParams">^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param>
    </interceptor-ref>
    <interceptor-ref name="conversionError"/>
    <interceptor-ref name="validation">
        <param name="excludeMethods">input,back,cancel,browse</param>
    </interceptor-ref>
    <interceptor-ref name="workflow">
        <param name="excludeMethods">input,back,cancel,browse</param>
    </interceptor-ref>
</interceptor-stack>

それが役立つことを願っています。

于 2014-01-09T13:05:49.370 に答える
0

あなたが与えたコードでは、トランスポーター クラスの宣言が見つかりません。

おそらく、Transpoter クラスに id と name だけでなく、2 つ以上のパラメーターがあるためだと思います。

実際、私が言及した状況では、このエラー メッセージが常に発生していました。

この問題を解決するには、id と name の 2 つの属性のみを持つデータ転送オブジェクト (DTO) を定義します。この DTO を使用して jsp からパラメーターを受け取り、属性値を Transporter オブジェクトに渡します。

私は 2019 年にこの問題を見て、解決策を提供し、将来他の人が使用できることを願っています。

于 2019-04-16T21:44:59.463 に答える