1

私はSpringに比較的慣れていないので、あまり明白ではないことがあります。つまり、コントローラーがシングルトンであるという事実。これは良いアプローチであることに同意しますが、他のフレームワークで実装していたものを実装することはできません。

全体で AJAX リクエストを使用する Web アプリケーションを構築しています。BaseController親としてのコントローラー階層があり、他のすべてのコントローラーはそれを拡張します。

クライアントに応答を返す必要があるコントローラー アクションは、@ResponseBodyアノテーションで注釈が付けられ、シリアル化された JSON 文字列をクライアントに返します。

createJSONResponse()このシリアル化を実行するメソッドは に実装されてBaseControllerおり、ここでの主なアイデアは、子コントローラーの各アクションがMap<String, Object> responseMapクライアント データに必要なマップを設定し、このマップに でアクセスしてBaseControllerシリアル化するというものです。

すべてのアクションで の新しいインスタンスを作成したくresponseMapないし、 のパラメータとして毎回渡したくありませんcreateJSONResponse()

プロパティとして宣言することで、他のフレームワークでこれを達成しresponseMapました。BaseControllerprotected

responseMapすべてのコントローラーがシングルトンであり、リクエストごとに新しいインスタンスを作成できないため、Spring でこれを行うことはできません。

BaseControllerリクエストをスコープにするのが良い考えかどうかはわかりません。

request スコープ Bean としてヘルパー クラスを作成し、このヘルパーで responseMap を宣言しました。次に、この Bean を のように注入し@AutowiredましたBaseControllercreateJSONResponse()このヘルパーのメソッドも移動しました。次に、コントローラーから、このマップを as として入力しhelper.responseMap.add(<somedata>)、 を呼び出しますhelper.createResponseMap()

この場合、 でresponseMap空になりcreateResponseMap()、コントローラ アクションで設定されたデータは含まれません。スレッドセーフでresponseMApはなく、非同期リクエストごとにスレッドからスレッドに移動しています。

必要な機能を実現する方法はありますか?


回避策 による解決: すべてのリクエストの前に responseMap をインスタンス化し、リクエスト インターセプターの HttpServletRequest オブジェクトに追加することで、問題を解決しました。次に、createJSONResponse() メソッドと responseMap の人口メソッドは、HttpServletRequest から responseMap を取得する getRequestMap() メソッドを参照します。

PS それでも、より良い解決策を知って喜んでいます。

4

1 に答える 1

0

これを正しく (スレッドセーフに) 行うために、ある時点で各リクエストに対してそのマップのインスタンスを 1 つ持つように強制されます (本当にそれをシングルトンに注入したい場合は、スコープ付きプロキシを使用できますが、まったく同じ結果になりますが、さらに複雑になります。

私のアドバイスは、テンプレート メソッドを利用して、その保護されたプロパティを取り除くことです。各サブクラスに入力されたマップを返す抽象メソッドを定義するだけです。

すべての具体的なコントローラーへの書き込みを取り除きたいだけの場合Map<String, Object> responseMap = new HashMap<String, Object>()は、ベースコントローラーで(すべてのリクエストに対して)それを行い、抽象メソッドを使用してそのマップを設定するだけです(ただし、インスタンスは毎回新しいものになります) )。

ベースコントローラーでの表示方法は次のとおりです。

public String handleRequest() {
    Map<String, Object> model = new HashMap<String, Object>();
    populateModel(model);
    model.put("success", true);  // as a response to your comment
    return serializeModel(model);
}

protected abstract void populateModel(Map<String, Object> model);

PS補足として(これはあなたの質問に対する実際の答えかもしれませんが)、Springは、型安全なオブジェクトとして返すだけで、応答をいくつかの形式でシリアル化できます。クラスパスに jackson マッパーを含め (JSON 形式を有効にするため)、モデル クラスに JAXB アノテーションを追加し、モデルをMyBeanインスタンスとして返すだけです。適切なヘッダーを提供するか、リクエストマッピングでAccept:適切に定義すると、Spring はそれを XML / JSON としてマーシャリングします。produces

于 2012-05-17T09:39:03.213 に答える