0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

🧩 Vol.11.20 複数フォームを安全に扱う!セッション管理と動的フォームの考え方

Last updated at Posted at 2025-05-29

複数のフォームを同一画面・複数画面で扱う際に起こりやすい「競合」「衝突」「セッション不整合」などの問題を防ぐための設計と実装方針を、Struts2の視点から整理して解説します。


✅ 1. なぜ複数フォームはトラブルを招くのか?

☑ 例:同一画面に複数フォームがある場合

<!-- 検索フォーム -->
<s:form action="searchUser">
  <s:textfield name="keyword" label="キーワード" />
  <s:submit value="検索" />
</s:form>

<!-- 新規ユーザ登録フォーム -->
<s:form action="createUser">
  <s:textfield name="username" label="ユーザ名" />
  <s:textfield name="email" label="メールアドレス" />
  <s:submit value="登録" />
</s:form>

🔥 起こりうる問題

  • どちらのフォームでエラーが起きたのか特定しづらい

  • 入力チェックが他のフォームにも影響を与える

  • セッションに一時保存していたデータが他のフォーム操作で上書きされる


✅ 2. 対策①:トークンでの二重送信防止(tokenInterceptor)

Struts2には tokenInterceptor が用意されており、同じフォームを2度送信することを防ぐのに有効です。

<s:form action="createUser">
  <s:token />
  <s:textfield name="username" label="ユーザ名" />
  <s:submit value="登録" />
</s:form>
<action name="createUser" class="CreateUserAction">
  <interceptor-ref name="token"/>
  <interceptor-ref name="defaultStack"/>
  <result name="invalid.token">duplicateSubmit.jsp</result>
  <result name="success">success.jsp</result>
</action>

🔐 注意:
複数のフォームで を使うと、同じセッション内で最後のトークンだけが有効になるため、
セッションに依存せず、JavaScriptで動的に送信先を切り替える方式も併用を検討します。


✅ 3. 対策②:フォーム単位での専用Action+専用Formクラス設計

❌ NGパターン:

public class UserAction extends ActionSupport {
    private String keyword; // 検索用
    private String username; // 登録用
    private String email;    // 登録用
    // フォームを兼ねたフィールドが混在
}

✅ OKパターン:

  • SearchUserAction(検索専用)

  • CreateUserAction(登録専用)

Actionクラスごとにフォームを完全に分離し、1アクション=1フォームの原則を守ることで、
フィールド競合・バリデーションの混乱を防止できます。


✅ 4. 対策③:セッション一時保存はスコープと命名を厳密に管理

☑ よくあるバグの元:

session.put("userInput", form);

→ 複数画面で同じキー名 "userInput" を使うと、他フォームの入力が上書きされる

✅ 改善例:

session.put("createUserForm", form);
session.put("editUserForm", form);

または、フォームの状態管理用にForm IDやタイムスタンプを付ける方法もあります。


✅ 5. 対策④:動的フォーム生成時はhidden+ID管理で状態を持つ

JavaScriptなどでフォームを動的に増やす場合:

<form action="editUser">
  <input type="text" name="username" />
  <input type="hidden" name="formId" value="create-1" />
</form>

サーバ側で formId を受け取り、セッション上のどのフォーム状態と対応するかを判断します。


✅ 6. よくあるケース:画面A → B → Cで途中セッション消える問題

セッションを多用したステップ式フォームの場合、別画面のアクセスによりセッションが破棄・上書きされることがあります。

✅ 対策:

  • 状態管理をセッションでなくDBやクッキーに移す
  • セッション内でも、画面単位でオブジェクト名を完全分離(例:createUser.step1, createUser.step2

✅ 7. テスト時に注目すべきポイント

  • タブを複数開いて操作してみる

  • バリデーションエラー後に戻って入力できるか

  • 戻るボタン・リロードで意図しないデータが送信されないか

  • セッションタイムアウト後の動作確認

🎯 まとめ

課題 解決策
フォーム同士の競合 Actionクラス・Formクラスの分離
二重送信 <s:token /> + tokenInterceptor
セッション上書き セッションキーを画面単位にする
フォーム状態の混乱 formId をhiddenで渡す
多画面セッション競合 セッション管理設計の明確化 or DB化

▶️ 次回予告:Vol.11.21 JSON返却の基本とStruts2 REST連携の仕組み

JSONベースのAPIレスポンスや、RESTful構成への第一歩として、Struts2での streamjson タイプの使い方と実例を解説します。


🧭 関連記事(Vol.11.xxxシリーズ)

連番 タイトル 内容分類
Vol.11.0 Struts2が提供してくれる便利機能まとめ9選 導入&概要
Vol.11.1 自動注入とステートレスActionの仕組み フレームワーク内部理解
Vol.11.2 UX改善に効く!アクション層設計と入力制御の極意(プロローグ) UX設計・アクション層総論
Vol.11.2.1 【実践編】Struts2アクション層の役割と設計パターン(Command型 / UIアクション分離など) アクション設計パターン
Vol.11.2.2 【UX重視】戻るボタン・キャンセル処理の設計手法と「戻り先管理」のスマート実装 戻り先制御とUX設計
Vol.11.2.3 【設計ノウハウ】多画面遷移時のパラメータ受け渡し・保持戦略(セッション vs hidden vs URL) パラメータ多重管理
Vol.11.2.4 【実践ガイド】ユーザー操作を考慮したアクション遷移設計(リダイレクト vs フォワードの使い分け) UX遷移設計/Result制御
Vol.11.2.5 【トラブル防止】アクション層の共通処理とメンテナブルなBaseAction設計 アクション共通化/保守性
Vol.11.3 Struts2の defaultStack とは?Interceptorの中身を詳しく追ってみる Interceptor
Vol.11.3.2 🔧 Vol.11.3.2 独自Interceptorの作り方と使い所 Struts2のカスタマイズを“実践で使えるレベル”に一歩進めよう Interceptor
Vol.11.4 入門者のための「パラメータ自動バインディング」完全理解ガイド 自動バインディング
Vol.Vol.11.4.1 入門者のための自動バインディング実践パターン集 自動バインディング
Vol.11.5 Struts2の構成理解が“実務レベル”へと進化する決定版 設定ファイル構造
Vol.11.5.1 Struts2の“画面遷移の全体像”を理解するためのマイルストーン記事 設定ファイル構造
Vol.11.6 ActionSupport の便利メソッドと国際化対応 ユーティリティ / i18n
Vol.11.7 validate() / input 戦略とUX設計 開発スタイルの違い
Vol.11.8 アノテーションベースの設定 vs XML定義の比較 開発スタイルの違い
Vol.11.9 バリデーション完全解説(XML / アノテーション) バリデーション(※Vol.8補完)
Vol.11.10 Struts2の「OGNL」ってなに?しくみと使い方をやさしく解説 式言語OGNL解説
Vol.11.11 ModelDriven インターフェースの使いどころと注意点 Model駆動開発
Vol.11.12 SessionAware と RequestAware でセッション/リクエスト管理 セッション管理
Vol.11.13 Resultタイプ完全解説(dispatcher / redirect / stream など) 遷移パターン理解
Vol.11.14 Vol.11.14 ValueStackの中身を理解する – 画面とActionの橋渡し役 Action
Vol.11.15 Interceptorチェーンを自作してみよう(ログ / 認証フィルタ) Interceptor
Vol.11.16 エラー処理と例外ハンドリングの実践パターン ハンドリング設計
Vol.11.17 Struts2でファイルアップロード機能を実装する方法 実装系Tips
Vol.11.18 非同期通信(AJAX)とStruts2の連携方法 フロント連携編
Vol.11.19 セキュリティ対策(CSRF, XSS, パラメータ偽装) セキュリティ対策
Vol.11.21 Struts2でJSONを返す!REST API連携と非同期通信の基本設計 セッション管理
Vol.11.22 本番環境構成とセキュリティ設計(Apache+Tomcat+Struts2連携) 外部公開

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?