本章では、掲示板アプリケーションの多くのアクションが継承して利用する、共通処理クラス BaseAction
について解説します。
1. BaseActionとは?
BaseAction
クラスは、Struts2で使用される共通アクションクラスです。
このクラスを継承することで、以下のような共通機能を全アクションクラスで使えるようになります:
- セッション情報の取得
- リクエスト情報の取得
- ユーザーIDやスレッドIDなどの保持
- リクエストパラメータの共通取得
- 処理メソッドの定義(
mainProc()
)
2. 実装しているインタフェース(Struts2独自)
Struts2 では、以下のインタフェースを実装することで、セッションやリクエスト情報が自動的に"注入" されます。
実装インタフェース | フレームワーク/Java | 注入されるオブジェクト | 説明 |
---|---|---|---|
SessionAware | Java | Map session | セッション情報を取得するためのIF |
ServletRequestAware | Struts2 | HttpServletRequest request | HTTPリクエストを取得するためのIF |
ServletResponseAware | Struts2 | HttpServletResponse response | HTTPレスポンスを扱うためのIF |
💬 補足:「注入される」とは?
Javaのクラスの中で
new
などを使って自分でオブジェクトを作るのではなく、
フレームワーク側が必要な情報を自動で渡してくれる 仕組みのことを「注入(インジェクション)」と言います。例)
session
やrequest
変数は自動的にセットされて利用可能になります!
3. BaseActionのコード(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
クラス
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 におけるログ出力処理の実装例
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
を使った例は以下の通りです:
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 を組み込み、全アクションでの共通的なエラー処理を実装することができます。
@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.5)では、この BaseAction
の活用例を具体的に紹介していきます!
CreateThreadAction
や PostAction
の中で、どのように活かされているかを詳しく見ていきましょう!