📘 Vol.6：BaseActionクラスの詳細解説【Struts2の要】

本章では、掲示板アプリケーションの多くのアクションが継承して利用する、**共通処理クラス `BaseActionクラス`** について解説します。

---

## 1. BaseActionクラスとは？

`BaseAction` クラスは、Struts2で使用される**共通アクションクラス**です。  
このクラスを継承することで、以下のような**共通機能**を全アクションクラスで使えるようになります：

- セッション情報の取得  
- リクエスト情報の取得  
- ユーザーIDやスレッドIDなどの保持  
- リクエストパラメータの共通取得  
- 処理メソッドの定義（`mainProc()`）

---

## 2. 実装しているインタフェース（Struts2独自）

Struts2 では、以下のインタフェースを実装することで、**セッションやリクエスト情報が自動的に"注入"** されます。

| 実装インタフェース         | フレームワーク/Java | 注入されるオブジェクト           | 説明                             |
|----------------------------|----------------------|-----------------------------------|----------------------------------|
| SessionAware               | Java                 | Map<String, Object> session       | セッション情報を取得するためのIF |
| ServletRequestAware        | Struts2              | HttpServletRequest request        | HTTPリクエストを取得するためのIF |
| ServletResponseAware       | Struts2              | HttpServletResponse response      | HTTPレスポンスを扱うためのIF     |


### 💬 補足：「注入される」とは？

> Javaのクラスの中で `new` などを使って自分でオブジェクトを作るのではなく、  
> **フレームワーク側が必要な情報を自動で渡してくれる** 仕組みのことを「注入（インジェクション）」と言います。  
>  
> 例）`session` や `request` 変数は自動的にセットされて利用可能になります！

---

## 3. BaseActionのコード（Java）

```java
package com.company.bulletinboard.interceptor;

import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;

public abstract class BaseAction implements SessionAware, ServletRequestAware, ServletResponseAware {

    protected Map<String, Object> session;
    protected HttpServletRequest request;
    protected HttpServletResponse response;

    protected String user_id;
    protected String thread_id;
    protected String board_id;
    protected String action;

    @Override
    public void setSession(Map<String, Object> session) {
        this.session = session;
        // セッションからログイン中のuser_idを取得して保持
        this.user_id = (String) session.get("user_id");
    }

    @Override
    public void setServletRequest(HttpServletRequest request) {
        this.request = request;
        // URLパラメータやリクエストスコープの情報を取得
        this.thread_id = request.getParameter("thread_id");
        this.board_id = request.getParameter("board_id");
        this.action = request.getParameter("action");
    }

    @Override
    public void setServletResponse(HttpServletResponse response) {
        this.response = response;
    }

    // 各アクションがオーバーライドして処理内容を記述
    public abstract String mainProc();
}
```
---

## 4. 継承クラスでの使われ方

この `BaseAction` を他のアクションクラスが継承し、共通の `mainProc()` メソッドをオーバーライドして実装します。

✅ 例：スレッド作成用の `CreateThreadAction` クラス

```java
public class CreateThreadAction extends BaseAction {

    @Override
    public String mainProc() {
        // BaseAction から引き継いだ board_id や user_id を使用可能
        System.out.println("掲示板ID: " + board_id);
        System.out.println("ログインユーザー: " + user_id);

        // スレッド作成処理をここで実装
        // ...

        return "success";
    }
}
```
---


## 5. リクエストで取得した値を使える理由

`BaseAction` で `ServletRequestAware` を実装しているため、  
Struts2 のライフサイクル中にリクエストが**自動的に注入**され、  
それによりパラメータ（例：`board_id`, `thread_id` など）を **どの継承先でも使える状態** にしています。

これにより、同じようなコードを何度も書かずに済む＝**DRY原則** を実現できます！

---

## 6. 共通ログ出力処理の実装

BaseAction には、**各アクションの処理開始・終了時にログを出力する共通ロジック**を組み込んでいます。

これにより、どのアクションでもログ出力コードを毎回書く必要がなくなり、**保守性と可読性が向上**します。

✅ 例：BaseAction におけるログ出力処理の実装例

```java
public abstract class BaseAction implements SessionAware, ServletRequestAware, ServletResponseAware {

    protected HttpServletRequest request;
    protected HttpServletResponse response;
    protected Map<String, Object> session;
    protected String user_id;
    protected String board_id;
    protected String thread_id;

    @Override
    public String execute() throws Exception {
        System.out.println("=== " + this.getClass().getSimpleName() + " 開始 ===");
        String result = mainProc();
        System.out.println("=== " + this.getClass().getSimpleName() + " 終了: result = " + result + " ===");
        return result;
    }

    public abstract String mainProc();
}
```

このように execute() の中でログ出力することで、全アクションの実行ログが自動的に記録されます。

このログ出力の共通化によって、次のようなメリットがあります：

- デバッグ時の トレース性が向上

- 処理の流れを 簡単に追跡できる

- エラー原因の早期発見 がしやすくなる

こうした 「共通ログ出力」も BaseAction を導入する大きな理由の一つ です。

なお、サンプルコードでは分かりやすさを優先して `System.out.println` を使用していますが、  
本番環境ではログフレームワーク（例：`org.slf4j.Logger` や `Log4j`）を利用することを強くおすすめします。  

ログフレームワークを使うことで以下のようなメリットがあります：

- ログレベル（INFO, DEBUG, ERRORなど）の柔軟な管理  
- ログの出力先（ファイル、コンソール、リモートサーバなど）の切り替えが簡単  
- フォーマットやローテーションなどの高度な設定が可能  

例えば、`Logger` を使った例は以下の通りです：

```java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BaseAction implements Action {
    private static final Logger logger = LoggerFactory.getLogger(BaseAction.class);

    @Override
    public String execute() throws Exception {
        logger.info("=== {} 開始 ===", this.getClass().getSimpleName());
        String result;
        try {
            result = mainProc();
        } catch (Exception e) {
            logger.error("エラー発生:", e);
            result = "error";
        }
        logger.info("=== {} 終了: result = {} ===", this.getClass().getSimpleName(), result);
        return result;
    }
}
```

このようにすれば、運用に適したログ管理ができ、開発・保守が一層効率的になります。



---

## 7. 共通エラーハンドリングの実装
BaseAction に try-catch を組み込み、全アクションでの共通的なエラー処理を実装することができます。


```java
@Override
public String execute() throws Exception {
    System.out.println("=== " + this.getClass().getSimpleName() + " 開始 ===");
    String result;
    try {
        result = mainProc();
    } catch (Exception e) {
        System.err.println("エラー発生: " + e.getMessage());
        e.printStackTrace();
        result = "error"; // 共通エラー画面などに遷移
    }
    System.out.println("=== " + this.getClass().getSimpleName() + " 終了: result = " + result + " ===");
    return result;
}
```

このようにすることで：

- 各アクションクラスで try-catch を書く必要がなくなる

- 共通のエラーページやログ記録処理に一元対応できる

- アプリ全体の安定性と信頼性が向上

といったメリットがあります。


---

## 8.Struts2 の Interceptor との併用による拡張性
Struts2 の Interceptor（インターセプター）機能と組み合わせることで、以下のような 関心の分離（Separation of Concerns） が可能になります：

| 処理       | 実装箇所                        |
| -------- | --------------------------- |
| 認証チェック   | Interceptor                 |
| ログ出力     | BaseAction（または Interceptor） |
| パラメータ処理  | BaseAction                  |
| アプリ固有の処理 | 各 Action クラスの `mainProc()`  |

✅ Interceptor との役割分担例
- Interceptor：認証チェック、トランザクション制御、入力検証 など

- BaseAction：パラメータ取得・共通ログ・エラー処理 など

- 各 Action クラス：ビジネスロジック（スレッド作成、投稿など）

このように設計することで、責務が明確化されて再利用性が高まり、保守性にも優れる構成になります。

---

## 9. まとめ

- BaseAction は「パラメータ処理」「共通ログ出力」「共通エラーハンドリング」などを担う基盤クラス  
- Struts2の機能で**セッション・リクエストなどが自動で「注入」**される  
- 継承先では `mainProc()` をオーバーライドして具体的な処理を記述  
- 画面遷移ごとに `request.getParameter()` を書かなくても済むのがポイント  

- Interceptor を併用することで、よりクリーンで拡張可能なアーキテクチャが実現できる

---

📝 **[📘 Vol.6.1 BaseAction の活用例【共通基底クラスでセッション管理を簡素化】](https://qiita.com/juehara-crypto/items/f4efded5b26e39e49928)では、この `BaseAction` の活用例を具体的に紹介していきます！**  
`CreateThreadAction` や `PostAction` の中で、どのように活かされているかを詳しく見ていきましょう！


---

## 🧭 Vol.1〜7 関連リンク

| 回 | タイトル | 主な内容 |
|----|----------|-----------|
| Vol.1 | [プログラミングとの再会 – 「画面ありき」で変わった学び方](https://qiita.com/juehara-crypto/items/2fcc53d765dcc25a4fa3) | プログラミング再入門と、**画面駆動の学習法**というユニークなアプローチの紹介。最初に「画面」から考えることでモチベーションを継続。 |
| Vol.2 | [画面駆動設計に基づく設計書の具体例：画面フローからUI設計・処理定義まで](https://qiita.com/juehara-crypto/items/c1fd34b3031b13160f27) | 実際に描いた**画面遷移図・UI設計・処理定義書**を公開し、画面中心の設計手法を解説。 |
| Vol.3 | [詳細設計編：ER図で見るデータ構造と実装の土台](https://qiita.com/juehara-crypto/items/6e6431954dc99ea59054) | 実装前提で設計された **ER図（Entity Relationship 図）** をもとに、データ構造と整合性を設計。 |
| Vol.4 | [Struts2とMavenの基礎と設定ファイルの役割](https://qiita.com/juehara-crypto/items/e37fa1879ae996bee73e) | Struts2の構成とMavenでの管理、`web.xml` や `pom.xml` の役割を丁寧に解説。 |
| Vol.5 | [環境構築編：掲示板アプリケーションの実行準備](https://qiita.com/juehara-crypto/items/7010ae45d35174d3a3a6) | TomcatとEclipseでの動作環境構築。 |
| Vol.6.1 | [BaseAction の活用例【共通基底クラスでセッション管理を簡素化】](https://qiita.com/juehara-crypto/items/f4efded5b26e39e49928) | BaseAction を継承する具体的なアクション例を紹介し、セッションやログ処理の統合例を実践。 |
| Vol.7 | [Struts2 における MVC モデルの全体像](https://qiita.com/juehara-crypto/items/761c0b13ed1a5f896bba) | Model-View-Controller の各要素が Struts2 でどう分担されるかを体系的に解説。 |
| Vol.7.1 | [Struts2 における Model（モデル）について](https://qiita.com/juehara-crypto/items/14f7f154caf29447ae93) | JavaBeansベースのModelクラス（User, Thread, Post など）設計とその役割を明確化。 |
| Vol.7.2 | [Struts2 における Controller（コントローラ）の責務](https://qiita.com/juehara-crypto/items/06b4f9296a296db8f4ba) | Actionクラスを軸に、入力処理・分岐処理・画面遷移の中核を担うControllerの実装指針を提示。 |
| Vol.7.3 | [Struts2 における struts.xml の書き方と役割](https://qiita.com/juehara-crypto/items/54dc2e0a4d56845a1a61) | URLマッピング、結果遷移、アクション定義の方法を丁寧に記述。初心者の詰まりやすいポイントを回避。 |
| Vol.7.4 | [struts.xmlの高度な設定と実践活用（Struts2）](https://qiita.com/juehara-crypto/items/bf03adbd840c8f4e2044) | namespaceの活用や画面単位での分離設計、開発時の保守性向上テクニックを紹介。 |
---