7

struts2-rest-plugin v.2.2.3 を使用する struts2 アプリケーションがあります。

アクションとそのメソッドへのリクエストのルーティングに関しては、すべてうまく機能しています。また、JSON や XML などの拡張機能を使用する場合は、シリアル化するオブジェクトを指定するために ModelDriven も使用しています。

私が抱えている問題は、POST または PUT 要求を Struts レイヤーに送信すると、空の応答が返されることです。

次のように POST リクエストをアクションに送信していますhttp://localhost:8080/alert-settings!update.json。そのメソッドにブレークポイントがあり、それが呼び出され、コードが実行されて完了します。問題は、ModelDriven インターフェイスを使用して応答を返そうとしていることであると感じています。何らかの理由で、rest-plugin がこれを気に入らないのですが、なぜそのように動作するのかわかりません。

rest プラグインの使用中に POST リクエストからの応答を受信することに関する既知の問題はありますか? 私はいたるところを見てきましたが、実際には何も見つかりません。

ご協力をお願いいたします。ご要望に応じて詳細をお知らせいたします。

4

3 に答える 3

4

同じ問題が発生しました。struts.xml ファイルに設定しようとしましたか:

struts.rest.content.restrictToGET = false

残りのプラグインのドキュメントの最後の設定を参照してください

于 2012-02-22T21:46:18.143 に答える
1

私は実際に、これが残りのプラグインの行であることがわかりました:

// don't return any content for PUT, DELETE, and POST where there are no errors
if (!hasErrors && !"get".equalsIgnoreCase(ServletActionContext.getRequest().getMethod())) {
  target = null;
}

これはorg.apache.struts2.rest.RestActionInvocationメソッドにありselectTarget()ます。場合によっては、POST、DELETE、および PUT 要求に対して応答オブジェクトを返すことができるオプションのように、REST アーキテクチャに実際には従わないため、これは非常に面倒です。

この問題を回避するには、次のように struts xml でこれを使用するように拡張RestActionProxyFactoryして指定します。RestActionInvocation

<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="restOverride" class="uk.co.ratedpeople.tp.rest.RPRestActionProxyFactory" />
<constant name="struts.actionProxyFactory" value="restOverride" />

これにより、POST リクエストでオブジェクトを返しながら、struts プラグインを使用できます。

RestActionProxyFactory

public class RPRestActionProxyFactory extends RestActionProxyFactory {

    @Override
    public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map extraContext, boolean executeResult, boolean cleanupContext) {
        if (namespace.startsWith(this.namespace)) {
            ActionInvocation inv = new RPRestActionInvocation(extraContext, true);
            container.inject(inv);
            return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
        } else {
            return super.createActionProxy(namespace, actionName, methodName, extraContext, executeResult, cleanupContext);
        }
    }

}

RestActionInvocation

public class RPRestActionInvocation extends RestActionInvocation {

    public RPRestActionInvocation(Map extraContext, boolean pushAction) {
        super(extraContext, pushAction);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void selectTarget() {

        // Select target (content to return)
        Throwable e = (Throwable)stack.findValue("exception");
        if (e != null) {

            // Exception
            target = e;
            hasErrors = true;

        } else if (action instanceof ValidationAware && ((ValidationAware)action).hasErrors()) {

            // Error messages
            ValidationAware validationAwareAction = ((ValidationAware)action);

            Map errors = new HashMap();
            if (validationAwareAction.getActionErrors().size() > 0) {
                errors.put("actionErrors", validationAwareAction.getActionErrors());
            }
            if (validationAwareAction.getFieldErrors().size() > 0) {
                errors.put("fieldErrors", validationAwareAction.getFieldErrors());
            }
            target = errors;
            hasErrors = true;

        } else if (action instanceof ModelDriven) {

            // Model
            target = ((ModelDriven)action).getModel();

        } else {
            target = action;
        }

        // don't return any content for PUT, DELETE, and POST where there are no errors
//      if (!hasErrors && !"get".equalsIgnoreCase(ServletActionContext.getRequest().getMethod())) {
//          target = null;
//      }
    }

}
于 2011-11-10T17:46:14.180 に答える
0

過去に、json、xml、タイルなどを返す結果の型が混在する struts アクションを使用したことがあります。それが推奨される方法かどうかはわかりませんが、規則が使用されていても、struts.xml を使用していくつかの構成が必要です。たぶん、あなたはすでにこれを行っているかもしれませんが、伝えるのに十分な情報が提供されていないかどうかはわかりません.

Struts.xml 設定:

<constant name="struts.convention.default.parent.package" value="restful"/>

<package name="restful"  extends="rest-default, struts-default, json-default">
    <result-types>
        <result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
        <result-type name="json" class="com.googlecode.jsonplugin.JSONResult"/>
    </result-types>

    ....
</package>

後で特定のアクションで使用する追加の結果タイプをセットアップしました。アクション クラスでは、アクションまたはメソッドごとに結果タイプを設定できます。

アクション クラス:

@Results({
    @Result(name = "JsonSuccess", type = "json"),
    @Result(name = "success", type = "tiles", location = "/tickets.tiles")
})

public class EventController extends RestActionSupport implements ModelDriven<EventBean>{
     ...
}

json の結果について他に注意すべき点があります。シリアル化可能なオブジェクトが結果として返される場合、そのオブジェクトに埋め込みオブジェクトを返す getter/setter を持つ他の複雑なオブジェクトが含まれている場合、しばしば空の結果を受け取ることに気付きました。または結果なし。多くの場合、埋め込みオブジェクトではなく Java 型 (String、int、Boolean など) のみを返す getter/setter を使用して、json の結果に使用する json ラッパー オブジェクトを作成することになります。デリゲートのゲッター/セッターを使用してこれを解決したと思いますが、戻って古いコードを確認する必要があります。

于 2011-11-17T14:37:22.750 に答える