📘 Vol.11.2.4「セッションとパラメータの使い分けと設計ポイント」

本記事では、Struts2ベースのWebアプリケーションにおける「セッションとパラメータの使い分け」について、実装例を交えて整理します。

画面遷移を伴うWebアプリケーションにおいて、「どの情報をセッションで保持し、どの情報をパラメータで渡すか」は、設計段階での重要な検討ポイントです。特に複数画面をまたぐ機能や、戻り先制御の実装時には、情報の保持手段がバグやユーザビリティに直結するためです。

---

### ✅ 1. なぜ「使い分け」が必要なのか？
例えば、以下のような画面遷移を想定します。

```plaintext
掲示板一覧 → 掲示板詳細 → スレッド詳細 → 投稿
```

このように「掲示板ID」「スレッドID」「ユーザーID」などが必要なデータは、各画面や処理で異なるライフサイクルを持っています。

| データ名   | 使用タイミング       | 適切な保持方法  |
| ------ | ------------- | -------- |
| ユーザーID | ログイン後〜ログアウトまで | セッション    |
| 掲示板ID  | 掲示板詳細参照時      | URLパラメータ |
| スレッドID | スレッド参照・投稿時    | セッション    |
| 投稿内容   | 一時的（フォーム入力）   | リクエスト    |


このように、「**情報のライフサイクル**」 に基づいて、保持方法を明確に分けることがポイントです。

---

### ✅ 2. セッションを使うべきケース


以下のようなケースではセッションを使うのが適しています。

- ログイン中のユーザー情報（ユーザーID、権限など）

- 投稿時の投稿時のスレッドID（同一スレッドへの連続投稿など）

- 「戻る」や「キャンセル」時に再表示する対象情報の保持

>📌 特に「戻る」や「投稿後に再表示する対象スレッド」は、URLに埋め込むのではなくセッションで持つことで、リダイレクト後も正しく再取得できます。


---

### ✅ 3. URLパラメータを使うべきケース

一方で、以下のような情報はURLパラメータとして渡すのが適しています。

- 掲示板ID（掲示板詳細を直接参照するケースが多いため）

- スレッドID（スレッド詳細リンクなど明示的な遷移時）

>📌 URLに情報が見えることで、ユーザーがブックマーク可能、またはSEO対応にもなる利点があります。

---

### 📝 4. 実装例（実プロジェクトに即した記述）
### ✅ PostAction.java 抜粋

投稿処理において、投稿対象の `thread_id` はセッションに保持されています。


```java
// セッションから thread_id を取得
Integer threadId = (Integer) session.get("thread_id");

// Postオブジェクトに thread_id を設定
post.setThread_id(threadId);

// 再度 thread_id をセッションに保存（PostListActionへの遷移のため）
session.put("thread_id", threadId);

```

- 投稿時に thread_id をセッションから取得し、投稿内容と紐づける。
- 画面遷移（例：投稿一覧再取得）後も同じスレッドが対象になるよう、thread_id をセッションに再格納している。

---

### ✅ BoardDetailAction.java 抜粋

掲示板ID`（board_id）`は、URLパラメータから取得しています。

```java
// URLパラメータから掲示板IDを取得（内部的にServletRequestを使用）
private int getBulletinboardIdFromUrl() {
    HttpServletRequest request = ServletActionContext.getRequest();
    int id = Integer.parseInt(request.getParameter("id"));
    logger.debug("Bulletinboard ID from URL: " + id);
    return id;
}
```

- URLに含まれる id をパースして、掲示板詳細取得・スレッド作成リンク用の処理に使用。
- このIDは、掲示板のスレッド一覧取得や、スレッド作成画面遷移のリンク生成に活用される。

---

### ✅ まとめ表

| データ名        | 使用箇所                        | 取得方法          | 保存対象     |
| ----------- | --------------------------- | ------------- | -------- |
| `user_id`   | ログイン後各画面共通                  | ログイン時セッションに格納 | セッション    |
| `thread_id` | 投稿処理 (`PostAction`)         | セッションから取得／保存  | セッション    |
| `board_id`  | 掲示板詳細 (`BoardDetailAction`) | URLパラメータから取得  | URL（明示的） |

---

### ✅ 5. 設計ポイントまとめ
- 一時的な操作対象（スレッドなど）はセッションに保持

- 複数ユーザーが閲覧・遷移できるもの（掲示板など）はURLパラメータで渡す

- 「戻る」「キャンセル」などの機能では、セッション上のIDを使って状態復元

このように設計することで、Struts2のリダイレクト・画面遷移に対応した、堅牢なWebアプリが実現できます。

---

### 🔍 補足：なぜ「掲示板ID」はURLパラメータで渡すのか？

掲示板ID`（board_id）`のような情報を「セッションで持てばいいのでは？」と考えるのは自然な発想です。
実際、`thread_id` はセッションで保持しているのだから、統一した方がスッキリするようにも思えます。

しかし、以下のような理由から「**掲示板IDはURLパラメータで渡す方が適している**」とされています。

---

### ✅ 理由①：直接アクセスやブックマークを許容したい場合

掲示板の詳細画面は、ログインユーザーであれば **誰でも見られる情報** です。
そのため、次のような使い方が求められます。

- URLを直接入力してアクセスできる

- ブックマークして後から再訪できる

- 他人にURLリンクを共有できる（社内チャット等）

こういった用途をサポートするには、`https://example.com/board/detail?id=3` のように、**URLにIDが含まれていることが重要**です。
一方、セッションで保持する方式では、前の画面を経由しないと正しく動作できません。

### ✅ 理由②：RESTful設計やWebの基本原則に則る
REST的な観点では、**URLは一意なリソースを表現するもの**とされます。

```bash
GET /board/detail?id=3 → 掲示板ID=3の詳細情報
```

このように明示的なURL設計にすることで：

- どのリソースを見ているかが明確になる

- クローラやリンク解析にも有利

- ブラウザの履歴・戻る機能とも親和性が高い

このため、**読み取り専用・共有可能な情報はURLパラメータで渡すのが自然**とされています。

---

### ✅ 理由③：「IDを見せたくない」場合はどうする？

「URLにIDを出したくない」「内部IDを見せるのがセキュリティ的に心配」というケースもあります。
その場合は、以下のような対策が考えられます。

✅ 方法1：トークンでマスキング

```
/board/detail?token=abcde12345

```
- トークンとIDの対応関係をサーバー側で管理。

- ユーザーにはIDを見せず、安全なURLでアクセス可能。


### ✅ 方法2：セッションに保持（ただし注意点あり）

- 前画面でセッションにIDを保存 → 詳細画面で使用。

- ただし、直接URLを開くことができない・戻る機能と相性が悪いなどの制約があります。

---

### ✅ 結論：設計目的に応じて使い分ける

| 使用ケース                 | URLパラメータ    | セッション保持 |
| --------------------- | ----------- | ------- |
| リンク共有、直接アクセス、再訪を許可したい | ✅ 向いている     | ❌ 不向き   |
| ログインユーザー専用・一時的な操作対象   | ❌ 不向き       | ✅ 向いている |
| IDを秘匿したい（セキュリティ的配慮）   | トークン方式などで対応 | ✅ 可能    |

---

このように、「**なぜURLパラメータなのか？」という観点を押さえることで、より明確な画面遷移設計ができる**ようになります。


 
---

## ✨ 補足A：セッションでIDを保持する設計例（実装あり）

### ✅ 目的

一時的な操作対象（スレッドIDなど）をセッションに保持することで、  
画面遷移後も状態を維持し、不要なパラメータの受け渡しを避けることができます。

---

### ✅ 使用ケースの一例（※本プロジェクトの設計とは異なる）

- スレッド詳細画面でスレッドIDをセッションに保存し、投稿画面でそのIDを利用
- 投稿完了後、セッションに保持していたIDを使って再表示する

> 💡 本プロジェクトでは「投稿フォームと投稿一覧」が同一のスレッド詳細画面に統合されています。  
> 本例は、画面分離型の設計パターンにおけるセッション活用例です。

---

### ✅ 実装例（PostAction.java）

```java
// セッションからスレッドIDを取得
Integer threadId = (Integer) session.get("thread_id");

// 投稿オブジェクトにスレッドIDをセット
post.setThread_id(threadId);

// 投稿データの保存処理など...

// 投稿完了後、同一スレッドの再表示に備えて再度スレッドIDをセッションに保存
session.put("thread_id", threadId);
```


---

✅ 利点と注意点

| 項目     | 内容                                     |
| ------ | -------------------------------------- |
| ✅ 利点   | URLがスッキリする／セキュリティ上IDを隠せる／リダイレクトで状態維持可能 |
| ⚠️ 注意点 | セッションに依存しすぎると、画面の再現性や状態管理が煩雑になる        |


---

✅ 活用のポイント
- IDをセッションに入れる対象は「一時的に操作するもの」に限定

- 投稿、編集、削除など「ユーザー固有の操作」において有効

- セッションタイムアウトや多重ログイン時の考慮も必要


---

### ✅ 説明補足

- 実装はあくまで「スレッド詳細 → 投稿 → 戻る」のような画面遷移型で使われる典型パターンの例です。
- 本プロジェクトでは、**画面遷移せずに同一画面内で完結する設計**のため、完全一致ではありません。
- しかし、読者が他のWebアプリ開発でセッション設計に悩んだ際に、参考になる構成となっています。

---




## ✨ 補足B：トークン方式でIDをURLから隠す方法（実装あり）

### ✅ 目的

URLにID（掲示板ID、スレッドIDなど）を表示したくない場合、  
ランダムなトークンに変換してやり取りすることで、IDを直接露出せずに遷移を実現できます。

---

### ✅ 使用ケースの一例

- 掲示板詳細画面やスレッド詳細画面へのアクセスに「ランダムトークン」を使う
- トークンと実IDの対応表をサーバー側（DBまたはセッション）で管理

> 💡 URLに `?id=123` のようにIDが表示されることを避けたいときに有効な設計です。

---

### ✅ 実装ステップ（簡易例）

#### 🔹 ステップ1：トークンを生成してセッションに保存

```java
// 例：掲示板IDからトークンを生成
String token = UUID.randomUUID().toString();
session.put("token_" + token, bulletinboardId);

// URLにトークンを付与してリンク生成
String url = "boardDetail.action?token=" + token;
```

🔹 ステップ2：トークンを受け取ってIDに変換
```java
HttpServletRequest request = ServletActionContext.getRequest();
String token = request.getParameter("token");

// セッションから実IDを取得
Integer boardId = (Integer) session.get("token_" + token);

if (boardId == null) {
    // 不正アクセス or 有効期限切れの処理
    return "error";
}
```

```text
画面 → トークン生成 → リンク生成 → トークン受信 → ID復元
```
---

### ✅ 利点と注意点

| 項目     | 内容                              |
| ------ | ------------------------------- |
| ✅ 利点   | IDをURLに表示しない／URLコピー・共有時にも安全性が向上 |
| ⚠️ 注意点 | トークンの有効期限・管理が必要／セッション肥大化に注意     |

---

### ✅ 活用のポイント
- セキュリティ重視の設計が必要な場面で有効（例：管理機能・内部画面）

- トークンの有効期限やアクセス権限を必ず検証する

- トークンをDBに保存する方式も可（ログインユーザー単位で管理）


---

### ✅ 応用例

- パスワード再発行メールでの一時トークンリンク

- 管理画面でのURL保護（内部IDを見せない）


---

### 🔍 補足のまとめ

- **補足A**は「セッションにIDを保持」するケース
- **補足B**は「URLにIDを見せずトークンに置き換える」ケース

両者とも、**「セキュリティ」や「画面状態の保持」を考慮した設計パターン**です。プロジェクトの要件に応じて、適切な方式を選ぶ指針として活用できます。

---

### ✨ シリーズまとめ（Vol.11.2.xx アクション層設計）

- [✅ Vol.11.2 UX改善に効く！アクション層設計と入力制御の極意（プロローグ） ― アクション層からはじめるStruts2の“わかりやすい画面遷移”と“操作性向上” ―](https://qiita.com/drafts/c69962826bb29639c351/edit)

- [✅ Vol.11.2.1 アクション層の役割と設計パターン ―「ただのリクエスト受け口」から「ユースケースの橋渡し役」へ―](https://qiita.com/juehara-crypto/items/9ca115073e6f928c7f71)

- [✅ Vol.11.2.2 アクションクラスの3設計スタイルと選定基準 ― 機能粒度・責務分離・保守性のバランスをどう取るか？ ― ](https://qiita.com/juehara-crypto/items/88b7634a64b1ad564668)

- [✅ Vol.11.2.3「戻り先制御と画面遷移の設計パターン」](https://qiita.com/juehara-crypto/items/c5165c92a4366fd1962b)

- [✅ Vol.11.2.5【トラブル防止】アクション層の共通処理とメンテナブルなBaseAction設計 ](https://qiita.com/juehara-crypto/items/b538b50eaa9c263a31bb)

---

### 🧭 関連記事（Vol.11.xxxシリーズ）
| 連番           | タイトル                                                  | 内容分類              |
| ------------ | ----------------------------------------------------- | ----------------- |
| [Vol.11.0](https://qiita.com/juehara-crypto/items/a0cc66893cb499a6e23a)     | Struts2が提供してくれる便利機能まとめ9選                              | 導入＆概要             |
| [Vol.11.1](https://qiita.com/juehara-crypto/items/0a584da537059dd43a7c)     | 自動注入とステートレスActionの仕組み                                 | フレームワーク内部理解       |
| [Vol.11.2](https://qiita.com/juehara-crypto/items/c69962826bb29639c351) | **UX改善に効く！アクション層設計と入力制御の極意（プロローグ）**                   | UX設計・アクション層総論     |
| [Vol.11.2.1](https://qiita.com/juehara-crypto/items/9ca115073e6f928c7f71)   | 【実践編】Struts2アクション層の役割と設計パターン（Command型 / UIアクション分離など）  | アクション設計パターン       |
| [Vol.11.2.2](https://qiita.com/juehara-crypto/items/88b7634a64b1ad564668)   | 【UX重視】戻るボタン・キャンセル処理の設計手法と「戻り先管理」のスマート実装               | 戻り先制御とUX設計        |
| [Vol.11.2.3](https://qiita.com/juehara-crypto/items/c5165c92a4366fd1962b)   | 【設計ノウハウ】多画面遷移時のパラメータ受け渡し・保持戦略（セッション vs hidden vs URL） | パラメータ多重管理         |
| [Vol.11.2.5](https://qiita.com/juehara-crypto/items/b538b50eaa9c263a31bb)   | 【トラブル防止】アクション層の共通処理とメンテナブルなBaseAction設計               | アクション共通化／保守性      |
| [Vol.11.3](https://qiita.com/juehara-crypto/items/913de7c942a9242201e8)     | Struts2の defaultStack とは？Interceptorの中身を詳しく追ってみる      | Interceptor       |
| [Vol.11.3.2](https://qiita.com/juehara-crypto/items/ede8d3c2a9b147f6161e)     | 🔧 Vol.11.3.2 独自Interceptorの作り方と使い所 _Struts2のカスタマイズを“実践で使えるレベル”に一歩進めよう_     | Interceptor       |
| [Vol.11.4](https://qiita.com/juehara-crypto/items/253142d13fe5f604610f)     | 入門者のための「パラメータ自動バインディング」完全理解ガイド                        | 自動バインディング         |
| [Vol.Vol.11.4.1](https://qiita.com/juehara-crypto/items/4fd8ed2a8be317f6e1bd)     | 入門者のための自動バインディング実践パターン集                        | 自動バインディング         |
| [Vol.11.5](https://qiita.com/juehara-crypto/items/6ef7a87a54163d81a9ba)     | Struts2の構成理解が“実務レベル”へと進化する決定版         | 設定ファイル構造          |
| [Vol.11.5.1](https://qiita.com/juehara-crypto/items/df407b24101e92a02eab)     | Struts2の“画面遷移の全体像”を理解するためのマイルストーン記事         | 設定ファイル構造          |
| [Vol.11.6](https://qiita.com/juehara-crypto/items/bfbdc2203acac7ba3f19)     | ActionSupport の便利メソッドと国際化対応                           | ユーティリティ / i18n    |
| [Vol.11.7](https://qiita.com/juehara-crypto/items/ed8f0977c23ee8c8b959)     | validate() / input 戦略とUX設計                            | 開発スタイルの違い    
| [Vol.11.8](https://qiita.com/juehara-crypto/items/bb2b23612c22fa9bf50b)     | アノテーションベースの設定 vs XML定義の比較                             | 開発スタイルの違い         |
| [Vol.11.9](https://qiita.com/juehara-crypto/items/6163ad6c9308cc8dda6d)     | バリデーション完全解説（XML / アノテーション）                            | バリデーション（※Vol.8補完） |
| [Vol.11.10](https://qiita.com/juehara-crypto/items/207cb3d7f0a889c54df9)     | Struts2の「OGNL」ってなに？しくみと使い方をやさしく解説                     | 式言語OGNL解説         |
| [Vol.11.11](https://qiita.com/juehara-crypto/items/c313ea56f97984756c05)    | ModelDriven インターフェースの使いどころと注意点                        | Model駆動開発         |
| [Vol.11.12](https://qiita.com/juehara-crypto/items/de7a17d53e53d6466f17)    | SessionAware と RequestAware でセッション/リクエスト管理            | セッション管理           |
| [Vol.11.13](https://qiita.com/juehara-crypto/items/539bd5bae75a8e154753)    | Resultタイプ完全解説（dispatcher / redirect / stream など）      | 遷移パターン理解          |
| [Vol.11.14](https://qiita.com/juehara-crypto/items/142d9aa2c623c5eb70bc)    | Vol.11.14 ValueStackの中身を理解する – 画面とActionの橋渡し役                 | Action            |
| [Vol.11.15](https://qiita.com/juehara-crypto/items/84f024816d0cf2212cb6)    | Interceptorチェーンを自作してみよう（ログ / 認証フィルタ）                 | Interceptor            |
| [Vol.11.16](https://qiita.com/juehara-crypto/items/ff3ad75f9ee45fcd0f8f)    | エラー処理と例外ハンドリングの実践パターン                                 | ハンドリング設計          |
| [Vol.11.17](https://qiita.com/juehara-crypto/items/0d8d5101ff39b34b4704)    | Struts2でファイルアップロード機能を実装する方法                           | 実装系Tips           |
| [Vol.11.18](https://qiita.com/juehara-crypto/items/d93c8d9cee719997c068)    | 非同期通信（AJAX）とStruts2の連携方法                              | フロント連携編           |
| [Vol.11.19](https://qiita.com/juehara-crypto/items/dd6cf06d3100c9204d1f)    | セキュリティ対策（CSRF, XSS, パラメータ偽装）                              | セキュリティ対策           |
| [Vol.11.20](https://qiita.com/juehara-crypto/items/9442d9f4705f1c6c4da1)    | 複数フォームを安全に扱う！セッション管理と動的フォームの考え方                              | セッション管理           |
| [Vol.11.21](https://qiita.com/juehara-crypto/items/78eb217727b7c97f228a)    | Struts2でJSONを返す！REST API連携と非同期通信の基本設計                              | セッション管理           |
| [Vol.11.22](https://qiita.com/juehara-crypto/items/424155ee0e567a36b9a1)    | 本番環境構成とセキュリティ設計（Apache+Tomcat+Struts2連携）                             | 外部公開           |

---