17

Spring MVC で、次のように @SessionAttribute タグを使用して SessionAttribute を定義するとします。

@SessionAttributes(value = "myModel")
public class MyController{
   ...
}

次のように、SessionStatus で status.setComplete() を呼び出すのを忘れたとします。

@RequestMapping(method = RequestMethod.POST)
public void doSomething(@ModelAttribute("myModel") MyModel model, SessionStatus status){
   ...
   //status.setComplete(); <-- Never gets called
}

モデルは永遠にセッションに留まりますか? ユーザーがサイトをナビゲートするにつれて、セッションがどんどん大きくなっていきますか?

4

3 に答える 3

22

コントローラーの終了後にセッション属性がクリアされるかどうかについては、大きな議論があります。

明確にするために、 Spring MVC 3.1.0 RELEASEソースコードを見ることができます。

インターフェースorg.springframework.web.bind.support.SessionAttributeStoreは、次のメソッドを公開します。

void storeAttribute(WebRequest request, String attributeName, Object attributeValue);

Object retrieveAttribute(WebRequest request, String attributeName);

void cleanupAttribute(WebRequest request, String attributeName);

デフォルトの実装はorg.springframework.web.bind.support.DefaultSessionAttributeStoreです

Eclipse のcleanupAttribute()で「Open Call Hierarchy」を実行すると、メソッドが 2 つの異なるフローによって呼び出されることがわかります。

1) org.springframework.web.method.annotation.ModelFactory

public void updateModel(NativeWebRequest request, ModelAndViewContainer mavContainer) throws Exception {

        if (mavContainer.getSessionStatus().isComplete()){
            this.sessionAttributesHandler.cleanupAttributes(request);
        }
        else {
            this.sessionAttributesHandler.storeAttributes(request, mavContainer.getModel());
        }

        if (!mavContainer.isRequestHandled()) {
            updateBindingResult(request, mavContainer.getModel());
        } 
    }

2) org.springframework.web.bind.annotation.support.HandlerMethodInvoker

public final void updateModelAttributes(Object handler, Map<String, Object> mavModel,
            ExtendedModelMap implicitModel, NativeWebRequest webRequest) throws Exception {

        if (this.methodResolver.hasSessionAttributes() && this.sessionStatus.isComplete()) {
            for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
                this.sessionAttributeStore.cleanupAttribute(webRequest, attrName);
            }
        }
...
}

どちらの場合も、セッション属性はthis.sessionStatus.isComplete()が呼び出されたときにのみ削除されることは明らかです。

DefaultSessionAttributeStoreのコードを掘り下げました。内部では、実際のHTTP セッションオブジェクトを取得して属性を保存するため、同じセッション内の他のコントローラーからアクセスできる可能性があります。

いいえ、セッション属性はクリーン POST 後に削除されません。

于 2012-02-17T15:54:50.670 に答える
12

編集#2:この答えはもはや正しくないことに注意してください。以下の@doanduyhaiの回答を参照してください。

編集: これは Spring 2.5 用であり、Spring 3.x 用であるとは限りませんが、必ずしも同じであるとは限らないことに注意してください。ドキュメントを再確認してください!

これは@Gandalfが言ったことに沿っています。

フォーム コントローラーは、フォームの最初の表示からフォームの送信まで、フォーム リクエストの有効期間をモデル化します。フォームが送信されると、フォーム コントローラーのジョブが完了し、コマンド オブジェクトがセッションから削除されます。

そのため、フォーム ワークフロー間のセッションでコマンド オブジェクトを保持するには、セッションを手動で管理する必要があります。クリーンな POST の後、オブジェクトはセッションから削除されます。

要するに、 setComplete() メソッドは単なる良い習慣ですが、必ずしも必須ではないと思います。

編集:これを確認するために、春の本を調べました。私はそれを引用します:

@SessionAttribute が使用されていない場合、バインディング エラーのためにフォームを再度レンダリングする場合でも、リクエストごとに新しいコマンド オブジェクトが作成されます。この注釈が有効になっている場合、コマンド オブジェクトは、フォームが正常に完了するまで、以降の使用のためにセッションに保存されます。その後、このコマンド オブジェクトはセッションから消去されます。 これは通常、コマンド オブジェクトが、変更を追跡するために異なる要求間で同一である必要がある永続オブジェクトである場合に使用されます。

本質的に、それは私が上で言ったことです。A) setComplete() を呼び出すか、B) コントローラーが POST を正常に完了するまで、セッションに保存します。

于 2009-06-01T21:58:32.823 に答える
1

あなたがそれをしたいと思う理由はありますか?

このスレッドから:@SessionAttribute問題

@SessionAttributesは、SimpleFormControllerのsessionFormと同じように機能します。最初のリクエストと最後のリクエストの間(ほとんどの場合、最初のGETと最後のPOST)の間、コマンド(または@SessionAttributesの場合は任意のオブジェクト)をセッションに配置します。その後、ものが削除されます。

于 2009-05-19T15:09:55.573 に答える