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.22 共通基底クラス BaseAction の作成(v2用)

Last updated at Posted at 2025-06-01

はじめに

前回の Vol.20 では、Struts2 アプリケーションの開発に必要な依存ライブラリを pom.xml に設定し、開発環境の基盤を整えました。

その上で今回の Vol.21 では、Struts2 における 共通基底クラス BaseAction の実装(v2) を紹介します。

すべてのアクションで共通して行われる処理(ログ出力、セッション・リクエストの取得など)を BaseAction に集約することで、コードの重複排除や保守性の向上を図るのが目的です。


📘 なお、本ブログでは以下の記事で BaseAction クラスの考え方や活用例についてすでに紹介しています:

これらの記事では BaseAction のv1実装をベースに説明していましたが、本記事では開発が進んだ v2 環境に対応する形で設計を整理・強化した BaseAction を再構築しています。


Struts2 のアクション設計において 「すべての処理の起点」 となるこのクラスの改修は、今後のアクション開発の効率性と統一性を高める上で非常に重要なステップです。


目次

  • 1.v1 との比較

  • 2.実装のポイント(v2)

  • 3.実装コード(BaseAction)

  • 4.使用例(PostAction)

  • 5.シーケンス図

  • 6.まとめ


1. v1 との比較表

項目 v1 v2 備考
ActionSupport 継承 Struts2 の基本機能を提供
SessionAware 実装 セッション情報を取得可能
ServletRequestAware 実装 リクエスト情報を取得可能
ロガー(Log4j) BaseActionで統一的なログ出力
共通実行メソッド execute() すべてのアクションで共通実行フロー
抽象メソッド mainProc() 各アクションはこのメソッドを実装
ログディレクトリの作成 初期化ブロックでlogs/ディレクトリを作成
getLoginUserId() の定義 セッションからログインユーザーID取得
getLoginUserName() の定義 セッションからログインユーザー名取得
セッション/リクエストの再利用支援 フィールド注入によりアクセスが容易になる

2. 実装のポイント(v2)

  • 全アクション共通のログ処理を BaseAction に実装

  • SessionAware, ServletRequestAware を実装してセッション・リクエスト取得を共通化

  • セッションからログインユーザーの情報を取得する getLoginUserId() / getLoginUserName() を定義

  • execute() は共通処理を行い、メイン処理は mainProc() に委譲


3. 実装コード(BaseAction.java)

package com.company.bulletinboard.interceptor;

import java.io.File;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionSupport;

/**
 * 【Bulletinboard v2】共通基底クラス BaseAction
 * 各アクションが継承し、共通の処理(ログ出力、セッション管理、リクエスト管理)を担当
 */
public abstract class BaseAction extends ActionSupport implements ServletRequestAware, SessionAware {

    protected static final Logger logger = LogManager.getLogger(BaseAction.class);

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

    static {
        // ログディレクトリの作成(初回のみ)
        File logDir = new File("logs");
        if (!logDir.exists()) {
            logDir.mkdirs();
        }
    }

    @Override
    public void setServletRequest(HttpServletRequest request) {
        this.request = request;
        logger.debug("BaseAction: HttpServletRequest set");
    }

    @Override
    public void setSession(Map<String, Object> session) {
        this.session = session;
        logger.debug("BaseAction: Session set");
    }

    /**
     * ログインユーザーIDの取得(セッションから)
     */
    protected String getLoginUserId() {
        Object userId = session.get("user_id");
        return userId != null ? userId.toString() : null;
    }

    /**
     * ログインユーザー名の取得(セッションから)
     */
    protected String getLoginUserName() {
        Object userName = session.get("user_name");
        return userName != null ? userName.toString() : null;
    }

    /**
     * 実行メソッド:共通処理+mainProc呼び出し
     */
    @Override
    public String execute() {
        String result = ERROR;

        logger.info("【処理開始】:" + this.getClass().getSimpleName());

        try {
            result = mainProc();
        } catch (Exception e) {
            logger.error("【エラー発生】:" + this.getClass().getSimpleName(), e);
        }

        logger.info("【処理終了】:" + this.getClass().getSimpleName());
        logger.debug("【Result】:" + result);

        return result;
    }

    /**
     * 各Actionで実装されるメイン処理
     */
    abstract protected String mainProc() throws Exception;
}


4. 使用例:PostAction クラス

public class PostAction extends BaseAction {

    @Override
    protected String mainProc() throws Exception {
        String userId = getLoginUserId();
        logger.info("投稿者ID:" + userId);

        // 投稿処理...

        return SUCCESS;
    }
}


5. シーケンス図:BaseAction 実行フロー

@startuml
actor User
participant "Struts2 フレームワーク" as Struts2
participant "SampleAction\n(BaseActionを継承)" as SampleAction
participant "BaseAction"
participant "DAO/Service"
database "DB" as DB

== リクエスト発行 ==
User -> Struts2 : HTTPリクエスト送信

== 実行対象アクションの決定 ==
Struts2 -> SampleAction : インスタンス生成

== セッション/リクエストの注入 ==
Struts2 -> SampleAction : setSession(session)
SampleAction -> BaseAction : setSession(session)\n継承によりBaseActionが処理
BaseAction -> BaseAction : this.session に保存

Struts2 -> SampleAction : setServletRequest(request)
SampleAction -> BaseAction : setServletRequest(request)\n継承によりBaseActionが処理
BaseAction -> BaseAction : this.request に保存

== 共通処理BaseAction ==
Struts2 -> BaseAction : execute() 呼び出し
BaseAction -> BaseAction : logger.info("処理開始")

== 個別処理オーバーライド ==
BaseAction -> SampleAction : mainProc() 呼び出し\nSampleAction側でオーバーライド

SampleAction -> DAO/Service : DBアクセススレッド取得
DAO/Service -> DB : SQL実行
DB --> DAO/Service : 結果返却
DAO/Service --> SampleAction : 業務データ返却

SampleAction --> BaseAction : 処理結果"success"

BaseAction -> BaseAction : logger.info("処理終了")
BaseAction -> Struts2 : 処理結果文字列"success"

== レスポンス生成 ==
Struts2 -> User : JSP等で画面描画
@enduml

📝 補足:セッション・リクエストの実体的な処理について
上記のシーケンス図では、Struts2 から SampleActionsetSession()setServletRequest() が呼び出されているように見えますが、実際の処理は BaseAction 側で行われています。
これは、SampleActionBaseAction を継承しており、BaseActionSessionAware および ServletRequestAware を実装しているためです。
したがって、Struts2 フレームワークは SampleAction に対してメソッドを呼び出しますが、その処理ロジックは BaseAction に定義されているものが実行されます。
継承関係により、共通のセッション・リクエスト管理がすべてのアクションで一元的に機能します。


6. まとめ

Struts2 アプリケーションでは、共通処理を抽象クラスに切り出すことで、以下のようなメリットが得られます:

  • コードの重複を減らし、保守性が向上

  • アクションごとの処理をシンプルに記述できる

  • セッションやリクエストへのアクセスが容易になる

  • ログ出力の統一により、デバッグ効率アップ

今後アクションを追加しても、BaseAction を継承するだけでログ・セッション・リクエスト処理を自動で引き継げます。ぜひご活用ください!


✅今後の予定

Vol. タイトル案 内容
Vol.20 🔄 pom.xmlの依存ライブラリの自動解決設定 EclipseのMavenプロジェクトでpom.xmlの依存関係を自動解決させる方法(Maven → Update Projectなど)
Vol.21 共通基底クラス BaseAction の作成 Struts2 のすべてのアクションで共通化される処理(セッション取得・ログ出力など)をまとめる
Vol.22 ログイン機能①:web.xmlの作成とStruts2起動確認 web.xml の役割、Struts2フィルタの設定、起点としての重要性と動作確認
Vol.23 ログイン機能②:JSP画面の作成(ログインフォーム) /WEB-INF/jsp/login.jsp の作成、フォームタグの使用、Struts連携確認
Vol.24 ログイン機能③:struts.xmlのルーティング設定 struts.xml におけるアクションマッピングの基本とログイン機能の設定
Vol.25 ログイン機能④:LoginActionクラスの作成 ユーザーID・パスワードの受け取り/認証処理との接続/BaseAction継承の活用
Vol.26 ログイン機能⑤:DB接続クラスとDAO層の作成 JDBCもしくはMyBatisの設定/UserDaoの骨組み/テスト接続確認
Vol.27 ログイン機能⑥:DB準備(テーブル作成) ログイン用のユーザーテーブルを作成し、初期データ挿入まで
Vol.28 ログイン機能⑦:ユーザー認証処理の実装 DAOで取得したユーザー情報を用いてログイン成功・失敗の分岐を作成
Vol.29 ログイン機能⑧:管理者ポータル画面の作成と遷移 ログイン成功後に「管理者ポータル画面」に遷移/各管理機能(掲示板・ユーザー・スレッド・投稿)へのリンク設置
Vol.30 管理機能①:掲示板管理画面の一覧表示の実装 既存の掲示板データを管理者画面に一覧表示する/DAO・JSP連携の確認
Vol.31 管理機能②:掲示板作成機能の実装 掲示板作成フォームの作成/作成後に一覧に戻る処理の流れ/バリデーション準備
Vol.32 管理機能③:掲示板編集機能の実装 編集対象掲示板の選択/情報の取得と更新/セッション引き継ぎとJSP反映
Vol.33 管理機能④:掲示板削除機能の実装 削除ボタンの配置/アクション・DAOによる物理削除処理と画面更新
Vol.34 管理機能⑤:ユーザー管理画面の一覧表示の実装 登録ユーザーを一覧表示/ユーザー編集・削除への遷移ボタン設置
Vol.35 管理機能⑥:ユーザー作成機能の実装 新規ユーザー追加フォーム/パスワード・権限などのバリデーション
Vol.36 管理機能⑦:ユーザー編集・削除機能の実装 ユーザー情報の更新/削除による整合性チェックと処理
Vol.37 管理機能⑧:スレッド管理画面の一覧表示と削除機能 掲示板ごとのスレッド表示と削除(掲示板IDでの紐づけ確認)
Vol.38 管理機能⑨:投稿管理画面の一覧表示と削除機能 各スレッドに紐づく投稿を一覧で表示/不適切投稿の削除処理
Vol.39 ログイン機能⑨:JSP表示にユーザー名を連携 セッションから取得し、画面上にユーザー名を表示する方法の実装
Vol.40 ログイン機能⑩:軽微なユニットテストとデバッグ活用 EclipseのJUnit/デバッグビューの使い方/ログ確認方法
Vol.41 今後の拡張方針:一般ユーザーポータルと投稿機能の導入へ 一般ユーザー向け機能へと発展/掲示板閲覧→スレッド作成→投稿までの基本設計

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?