Spring MVCのセッションオブジェクト管理の調査
layers Dev/Java/Spring Boot
label
Java
label
Spring Boot
label
Spring Session
label
Redis
date_range
更新日時 : 2021/03/13 11:04 date_range
投稿日時 : 2021/03/13 10:59概要
厳密にはSpring Sessionだが、業務でSpring MVC+Redisを使用したWebアプリを開発していて、Controllerクラスのセッションに関する動作を検証した。
- Spring MVC+Redisを使用
SessionAttributes
アノテーションでセッションオブジェクトを管理- 特定動作完了後にセッション中のオブジェクトを削除またはセッションを破棄する
用意したクラス
UserController
UserForm
オブジェクトをSessionで管理する@SessionAttributes
を付与
UserNextController
UserForm
オブジェクトをSessionで管理するが、値設定はしない@SessionAttributes
を付与
UserSessionCompleteController
@SessionAttributes
を付与しない
実行するメソッド
org.springframework.web.bind.support.SessionStatus.setComplete
- Session中のオブジェクトを明示的に削除する
javax.servlet.http.HttpSession.invalidate
- Sessionを明示的に破棄する
application.properties
の設定値
デフォルトのまま
キー | デフォルト値 | 説明 |
---|---|---|
spring.session.redis.configure-action | notify-keyspace-events | ユーザー定義の ConfigureRedisAction Bean が存在しない場合に適用する構成アクション。 |
spring.session.redis.flush-mode | on-save | セッションフラッシュモード。セッションの変更をセッションストアに書き込むタイミングを決定します。 |
spring.session.redis.namespace | spring:session | セッションの保存に使用されるキーの名前空間。 |
spring.session.redis.save-mode | on-set-attribute | セッション保存モード。セッションの変更を追跡し、セッションストアに保存する方法を決定します。 |
UserController
- 同じController内での画面制御結果
セッションオブジェクトの削除
setCompleteパターン | 1 | 2 | 3 | 4 |
---|---|---|---|---|
画面遷移 | /user/input | /user/detail | /user/complete | /user/detail |
画面説明 | 入力フォーム | 入力値表示 | 同ControllerでsessionState.setComplete | 入力値表示 |
セッションID | X | X | X | X |
formの値(初期をAとする) | A | A | A | formオブジェクトが取得できない |
- セッションIDは変更されない
- セッションオブジェクトであるUserFormが削除され、
HttpSessionRequiredException
が発生する
セッションの削除
invalidateパターン | 1 | 2 | 3 | 4 |
---|---|---|---|---|
画面遷移 | /user/input | /user/detail | /user/next/discard | /user/detail |
画面説明 | 入力フォーム | 入力値表示 | 別Controllerでsession.invalidate | 入力値表示 |
セッションID | X | X | X | Y |
formの値(初期をAとする) | A | A | A | A |
- セッションIDが変更される
- セッションオブジェクトはID変更後も保持される
UserNextController
- 同じセッションオブジェクトを
@SessionAttributes
に設定した別クラスでの画面制御結果 - 結果は
UserController
と変わらず
セッションオブジェクトの削除
setCompleteパターン | 1 | 2 | 3 | 4 |
---|---|---|---|---|
画面遷移 | /user/input | /user/detail | /user/next/complete | /user/detail |
画面説明 | 入力フォーム | 入力値表示 | 同ControllerでsessionState.setComplete | 入力値表示 |
セッションID | X | X | X | X |
formの値(初期をAとする) | A | A | A | formオブジェクトが取得できない |
- セッションIDは変更されない
- セッションオブジェクトであるUserFormが削除され、
HttpSessionRequiredException
が発生する
セッションの削除
invalidateパターン | 1 | 2 | 3 | 4 |
---|---|---|---|---|
画面遷移 | /user/input | /user/detail | /user/next/discard | /user/detail |
画面説明 | 入力フォーム | 入力値表示 | 別Controllerでsession.invalidate | 入力値表示 |
セッションID | X | X | X | Y |
formの値(初期をAとする) | A | A | A | A |
- セッションIDが変更される
- セッションオブジェクトはID変更後も保持される
UserSessionCompleteController
@SessionAttributes
に設定しない別クラスでの画面制御結果- 同クラス内でsessionCompleteしてもセッションオブジェクトは削除されない
- 同クラス内でinvalidateすると、セッションID変更とオブジェクトも削除される
- 上記結果と異なり、オブジェクトは新しいセッションに引き継がれない
セッションオブジェクトの削除
setCompleteパターン | 1 | 2 | 3 | 4 |
---|---|---|---|---|
画面遷移 | /user/input | /user/detail | /user/session/complete | /user/detail |
画面説明 | 入力フォーム | 入力値表示 | 別ControllerでsessionState.setComplete | 入力値表示 |
セッションID | X | X | X | X |
formの値(初期をAとする) | A | A | formオブジェクトが取得できない | A |
画面説明 | 入力フォーム | 入力値表示 | 別ControllerでsessionState.setComplete | 入力値表示 |
- セッションIDは変更されない
- セッションオブジェクトも削除されず、残ったまま
セッションの削除
invalidateパターン | 1 | 2 | 3 | 4 |
---|---|---|---|---|
画面遷移 | /user/input | /user/detail | /user/next/discard | /user/detail |
画面説明 | 入力フォーム | 入力値表示 | 別Controllerでsession.invalidate | 入力値表示 |
セッションID | X | X | X | Y |
formの値(初期をAとする) | A | A | formオブジェクトが取得できない | formオブジェクトが取得できない |
- セッションIDが変更される
- セッションオブジェクトも削除される
HttpSessionRequiredException
が発生する
まとめ
@SessionAttributes
を付与したクラス内でHttpSession.invalidate
メソッドを呼び出してもセッション中のオブジェクトは削除されず、sessionIdが変更されてオブジェクトは残ったままとなる@SessionAttributes
を付与したクラス内でSessionStatus.setComplete
を実行すると、削除される。@SessionAttributes
を付与していないクラスでHttpSession.invalidate
を実行すると、セッションIDの書き換えとともにオブジェクトも削除される
個人的には1.と3.について実装でハマる可能性があるかなと感じた。本来Spring MVC利用していて、HttpSessionを直接操作すること自体は減らす必要があるが、もし必要になった場合は参考にしてほしい。