解説 · セクション 7
セッションとキャスト
HttpSession から取り出した Object を元の型にダウンキャストするときの注意。
身近に置き換えると
遊園地の「入場リストバンド」と「手荷物預かり所」を想像してください。
Webサイトは通常、ページを移動するたびに「あなたが誰か」を忘れてしまいます。そこで、ログイン時に「リストバンド(HttpSession)」を渡し、あなた専用の「手荷物預かり所」を用意します。
預かり所にはどんな荷物でも預けられますが(setAttribute)、取り出すときは中身が何であれ「ただの荷物(Object)」として渡されます。そのため、受け取る側が「これはカメラだ」と明示的に確認(ダウンキャスト)しなければ使えません。そして帰るときは、リストバンドをハサミで切って(invalidate)すべてをリセットします。
3 行でまとめると
req.getSession()で自分専用の保管庫(セッション)を取得し、setAttributeでデータを保存する。getAttributeで取り出すデータはすべて「Object型」になるため、元の型に戻す「ダウンキャスト」が必須。- ログアウト時などは
invalidate()を呼んで、保管庫を安全に破棄する。
図で見ると
sequenceDiagram
participant B as ブラウザ
participant S as Servlet
participant H as HttpSession
B->>S: ログイン要求
S->>H: req.getSession() で取得
S->>H: setAttribute("user", user)
(User型を預ける)
B->>S: マイページ要求
S->>H: getAttribute("user")
H-->>S: Object型 として返却
Note over S: (User) でダウンキャストして復元
B->>S: ログアウト要求
S->>H: invalidate() で破棄
ページをまたいでも、同じリストバンド(セッションID)を持っていれば、サーバー側で以前預けたデータを取り出すことができます。
順を追って理解する
1. セッションを取得する
req.getSession() を呼び出すと、リクエストを送ってきたユーザー専用の HttpSession オブジェクトが取得できます。まだ存在しない場合は、新しく作成されます。
2. データを保存する
session.setAttribute("キー名", 保存したいオブジェクト) を使ってデータを預けます。キー名は、後で取り出すときの「引換券」の役割を果たします。
3. データを取り出してキャストする
別のページで session.getAttribute("キー名") を呼び出すとデータを取り出せます。ただし、セッションはどんな型でも預かれるように設計されているため、戻り値はすべて Object 型になります。元のオブジェクトとして使うには、(User) のように ダウンキャスト を行う必要があります。
4. 間違った型へのキャスト(ClassCastException)
もし "user" というキーで String を預けていたのに、取り出すときに (User) にキャストしようとすると、Javaは「型が違う」と判断し、実行時に ClassCastException というエラーを発生させます。預けた型と取り出す型は必ず一致させなければなりません。
5. セッションを破棄する
ユーザーがログアウトするときは、session.invalidate() を呼び出します。これにより、セッション内のデータがすべて消去され、セキュリティが保たれます。
応用ではこう書く
// --- ログイン処理を行う Servlet ---
HttpSession session = req.getSession();
User loginUser = new User("Taro", "taro@example.com");
// セッションに User オブジェクトを保存
session.setAttribute("user", loginUser);
// --- マイページを表示する Servlet ---
HttpSession session = req.getSession();
// getAttribute は Object 型を返すため、(User) でダウンキャストする
User user = (User) session.getAttribute("user");
if (user != null) {
// キャストしたことで、User クラスのメソッドが呼べるようになる
System.out.println("ようこそ、" + user.getName() + "さん");
} else {
System.out.println("ログインしていません");
}
// --- ログアウト処理を行う Servlet ---
HttpSession session = req.getSession();
// セッションを破棄(保存されていたデータもすべて消去される)
session.invalidate();
MVCアーキテクチャでは、Controller(Servlet)で取得したデータをセッションに保存し、View(JSPなど)や別のControllerで取り出して使う、という流れが基本になります。
よくある誤解
誤解: getAttribute で取り出した値は、そのまま元の型の変数に入れられる
正しくは: getAttribute の戻り値は常に Object 型です。そのため、User user = session.getAttribute("user"); と書くとコンパイルエラーになります。必ず User user = (User) session.getAttribute("user"); のように、明示的にキャストの記述をする必要があります。
誤解: invalidate() を呼ばなくても、ブラウザを閉じればセッションはすぐに消える
正しくは: ブラウザを閉じるとセッションID(リストバンド)が失われるためアクセスできなくなりますが、サーバー側のセッションデータ自体は一定時間(デフォルトで30分など)残り続けます。ログアウト機能を作る際は、必ず invalidate() を明示的に呼んで即座に破棄するのが安全です。
つまずいたら
このトピックで詰まったら基礎復習へ: 章 3 クラスの継承 (キャスト周り)