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.4.1 入門者のための自動バインディング実践パターン集 _Struts2 ParametersInterceptor × OGNLバインディングの“効きどころ”をケース別に完全図解_

Last updated at Posted at 2025-05-28

✅ はじめに

前回の Vol.11.4 では、Struts2の自動バインディングの仕組みと、ParametersInterceptor の役割について解説しました。

本記事では、実際のフォーム入力と Action クラスのプロパティ間でどのようにデータがバインドされるのかを、具体的なパターンごとに図解的に整理して解説します。


🗂️ 目次

  1. 単純なプロパティのバインディング
  2. 配列とListのバインディング
  3. Map形式のバインディング
  4. チェックボックス・複数選択のケース
  5. バインディング失敗・型変換エラー時の挙動
  6. オブジェクト型プロパティのネスト
  7. 補足:バインディング対象を制御するには?
  8. まとめと次回予告

1. 単純なプロパティのバインディング

もっとも基本的な構成。フォームから送信された入力値が、Actionクラスのプロパティにそのままマッピングされます。

HTMLフォーム:

<input type="text" name="userId" />

Actionクラス:

private String userId;

public void setUserId(String userId) {
    this.userId = userId;
}

2. 配列とListのバインディング

フォーム名に [インデックス] を指定すれば、配列やListにもバインドできます。

HTMLフォーム:

<input type="text" name="userIds[0]" />
<input type="text" name="userIds[1]" />

Actionクラス:

private List<String> userIds = new ArrayList<>();

public void setUserIds(List<String> userIds) {
    this.userIds = userIds;
}

📝補足:
JSで動的にフォームを生成する場合、userIds[] のように記述し、送信前にインデックスを付ける手法も一般的です。

"You can loop them by name or something, and change their name with JavaScript by assigning the right index."
— Stack Overflow

3. Map形式のバインディング

フォーム名に map['key'] 形式を使うことで、Mapにもバインド可能です。

HTMLフォーム:

<input type="text" name="params['key1']" />
<input type="text" name="params['key2']" />

Actionクラス:

private Map<String, String> params = new HashMap<>();

public void setParams(Map<String, String> params) {
    this.params = params;
}

4. チェックボックス・複数選択のケース

チェックボックスや複数選択のselectは、複数の値が一括でバインドされます。

HTMLフォーム:

<input type="checkbox" name="selectedIds" value="1" />
<input type="checkbox" name="selectedIds" value="2" />

Actionクラス:

private String[] selectedIds;

public void setSelectedIds(String[] selectedIds) {
    this.selectedIds = selectedIds;
}

5. バインディング失敗・型変換エラー時の挙動

例:数値型のフィールドに文字列が送信されると、変換エラーになります。

HTMLフォーム:

<input type="text" name="age" value="twenty" />

Actionクラス:

private int age;

public void setAge(int age) {
    this.age = age;
}

この場合 age には正しく値がバインドされず、型変換エラーが発生します。Struts2は変換エラーを検知し、適切にエラーメッセージを生成します。


6. オブジェクト型プロパティのネスト

Struts2では、リクエストパラメータのキー名に「.(ドット)」を使うことで、ネスト構造のモデルオブジェクトにも自動で値がセットされます。

🧩 ケース概要

例えば、User モデルの中に name プロパティを持つ場合、以下のようなリクエストパラメータが送られることで:

user.name=Taro

Struts2は ParametersInterceptor を通じて以下のような連鎖的バインディング処理を行います:

🔁 自動バインディングの流れ

  1. "user.name" というキーを検出
  2. アクションの getUser() を呼び出し、戻り値として User オブジェクトを取得
  3. その User オブジェクトに対して、setName("Taro") を実行
user.name
    ↓
getUser()
    ↓
Userオブジェクト
    ↓
setName("Taro")

このように、「ネスト構造のオブジェクトにも値をセットできる」 のがStruts2のOGNL×ParametersInterceptorの強みです。

💡 実装例

🔹 アクションクラス(Action)

public class RegisterAction extends ActionSupport {

    private User user = new User();

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String execute() {
        // user.getName() や user.getEmail() などを使って処理
        return SUCCESS;
    }
}

🔹 モデルクラス(User.java)

public class User {
    private String name;
    private String email;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

🔹 HTMLフォーム(JSPなど)

<s:form action="register">
    <s:textfield name="user.name" label="名前"/>
    <s:textfield name="user.email" label="メールアドレス"/>
    <s:submit value="登録"/>
</s:form>

🧠 補足:get/set 両方定義する理由
実は、技術的には getUser() だけでも内部的に User インスタンスが取得できるため、バインディングは可能です。
ただし、以下の理由から setUser() も合わせて定義するのが実務では一般的 です。

  • DIやユニットテストの都合(モック注入や差し替えが可能に)

  • 保守性の向上(将来的に User の生成方法を差し替える可能性)

  • プロジェクトの設計統一(全フィールドに対してget/setペアを定義)

✅ ポイントまとめ

パターン バインディング方式 備考
user.name=Taro getUser()setName() OGNL によるネスト解決
getUser() のみ定義 動作するが保守性にやや難あり 推奨されない設計
getUser() + setUser() 両方定義 ◎ベストプラクティス 実務ではこの形が主流

🧭 OGNLとParametersInterceptorの連携によって、Struts2はJavaBeans風オブジェクトのプロパティに対しても「パス指定で値を注入する」ことができます。このパターンを理解すれば、複雑なフォームでも柔軟に対応できます!


7. 補足:バインディング対象を制御するには?

Struts2では以下のような制御が可能です。

  • excludeParams:特定のパラメータを除外

  • includeParams:許可するパラメータを明示

  • paramsPrepareParamsStack:Prepare処理 → パラメータ設定 の順に制御できるStack

"This interceptor gets all parameters from ActionContext and sets them on the ValueStack via OGNL."
— Apache Struts: Parameters Interceptor


8. まとめと次回予告

本記事では、Struts2における 自動バインディングの実際の動作 を、以下のようなパターン別に解説しました:

  • 単純なプロパティ

  • オブジェクトネスト

  • 配列・リスト

  • Map形式

  • チェックボックス・セレクト

  • 型変換エラーの挙動


👉 次回予告
Vol.11.5:struts.xml完全理解ガイド(仮)
設定ファイルの構成・設計・ベストプラクティスを深掘りしていきます。


🧭 関連記事(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.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.20 複数フォームを安全に扱う!セッション管理と動的フォームの考え方 セッション管理
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?