Java(Seasar2)でインターセプターによるActionメソッドの前処理・後処理

Programming プログラミング
この記事は約7分で読めます。

Java(Seasar2)のSAStrutsで、Actionメソッドの前処理・後処理として、ログの出力や、認証チェック処理などの共通的な処理を入れたい。

そんな場合は、「Interceptor(インターセプター)」とやらを使用すれば楽にできるみたい。

とりあえずやってみた。

なお、今回のバージョンは以下です。

  • Eclipse 4.2 Juno
  • JDK 7u15
  • Apache Tomcat 7.0.35
スポンサーリンク

AbstractInterceptorクラスを継承したインターセプタークラスの作成

まずは、「AbstractInterceptor」クラスを継承し、「invoke」をオーバーライドさせる。

今回は、クラス名を「ActionInterceptor」とした。

以下のように、「Object object = invocation.proceed();」の部分で、Actionなどの制御に移るらしく、ここより前に処理を書けば前処理に、後ろに処理を書けば後処理になる。

なお、ここでは「Executeアノテーション(@Execute)」がついているActionメソッドかどうかを判定している。

「Executeアノテーション(@Execute)」がついているActionメソッドのみを対象としないと、全てのメソッドが引っかかってしまい、不要なログまで出ていたので。

Actionメソッドならほぼ全部に「Executeアノテーション(@Execute)」がついているはず。

package jp.co.sample.interceptor;

import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;
import org.seasar.framework.aop.interceptors.AbstractInterceptor;
import org.seasar.struts.annotation.Execute;

public class ActionInterceptor extends AbstractInterceptor {

	// 変数
	Logger logger = Logger.getLogger(getClass());

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {

		// Executeアノテーションの場合
		if (isExecuteMethod(invocation)) {

			// 前処理
			before(invocation);
		}

		// 主処理
		Object object = invocation.proceed();

		// Executeアノテーションの場合
		if (isExecuteMethod(invocation)) {

			// 後処理
			after(invocation);
		}

		return object;
	}

	private String getActionName(MethodInvocation invocation) {

		// 変数
		String className;
		String methodName;
		String actionName;

		// アクション名取得
		className = getTargetClass(invocation).getSimpleName();
		methodName = invocation.getMethod().getName();
		actionName = className + "#" + methodName;

		// アクション名返却
		return actionName;
	}

	private Boolean isExecuteMethod(MethodInvocation invocation) {

		// Executeアノテーション真偽値返却
		return invocation.getMethod().isAnnotationPresent(Execute.class);
	}

	private void before(MethodInvocation invocation) {

		// ログ出力
		logger.info(getActionName(invocation) + "を開始します。");
	}

	private void after(MethodInvocation invocation) {

		// ログ出力
		logger.info(getActionName(invocation) + "を終了します。");
	}
}

app.diconにインターセプターを登録

続いて、上記で作成したインターセプターを「app.dicon」ファイルに登録する。

「app.dicon」ファイルの場所は、「/プロジェクト名/src/main/resources/app.dicon」。

実際の書き方はこんな感じ。

1行追加しただけ。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
	"http://www.seasar.org/dtd/components24.dtd">
<components>
  <include path="convention.dicon"/>
  <include path="aop.dicon"/>
  <include path="j2ee.dicon"/>
  <include path="s2jdbc.dicon"/>
  <component name="actionMessagesThrowsInterceptor" class="org.seasar.struts.interceptor.ActionMessagesThrowsInterceptor"/>
  <component name="actionInterceptor" class="jp.co.sample.interceptor.ActionInterceptor"/>
</components>

customizer.diconにインターセプターを追加

最後に、上記で作成したインターセプターを「customizer.dicon」ファイルに追加する。

「customizer.dicon」ファイルの場所は、「/プロジェクト名/src/main/resources/customizer.dicon」。

追加する場所は、「actionCustomizer」の下に「addCustomizer」で追加する。

以下のような感じ。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
	"http://www.seasar.org/dtd/components24.dtd">
<components>
  <include path="default-customizer.dicon"/>

  <component name="formCustomizer" class="org.seasar.framework.container.customizer.CustomizerChain"/>
  <component name="actionCustomizer" class="org.seasar.framework.container.customizer.CustomizerChain">
    <initMethod name="addAspectCustomizer">
      <arg>"actionMessagesThrowsInterceptor"</arg>
    </initMethod>
    <initMethod name="addCustomizer">
      <arg>traceCustomizer</arg>
    </initMethod>
    <initMethod name="addCustomizer">
      <arg>
        <component class="org.seasar.framework.container.customizer.TxAttributeCustomizer"/>
      </arg>
    </initMethod>
    <initMethod name="addCustomizer">
      <arg>
        <component class="org.seasar.struts.customizer.ActionCustomizer"/>
      </arg>
    </initMethod>
    <initMethod name="addCustomizer">
      <arg>
        <component class="org.seasar.framework.container.customizer.AspectCustomizer">
          <property name="interceptorName">"actionInterceptor"</property>
          <property name="pointcut">".*"</property>
          <property name="useLookupAdapter">false</property>
        </component>
      </arg>
    </initMethod>
  </component>
  <component name="serviceCustomizer" class="org.seasar.framework.container.customizer.CustomizerChain">
    <initMethod name="addCustomizer">
      <arg>traceCustomizer</arg>
    </initMethod>
    <initMethod name="addCustomizer">
      <arg>
        <component class="org.seasar.framework.container.customizer.TxAttributeCustomizer"/>
      </arg>
    </initMethod>
  </component>
</components>

動作確認

以上の設定で、動作を確認してみる。

以下のように、無事に目的のログが出力されていました。

INFO  2013-12-17 21:52:31,669 [http-bio-8080-exec-4] IndexAction#indexを開始します。
INFO  2013-12-17 21:52:31,669 [http-bio-8080-exec-4] IndexAction#indexを終了します。
INFO  2013-12-17 21:52:31,963 [http-bio-8080-exec-6] LoginAction#Indexを開始します。
INFO  2013-12-17 21:52:31,963 [http-bio-8080-exec-6] LoginAction#Indexを終了します。

なお、Log4Jに関しては、こちらの記事参照⇒「Java(Seasar2)で「Log4J」によるログ出力の設定

GitHub(ソースはこちらで公開中)

Actionインターセプター(Actionメソッドの共通前処理・後処理)

参考サイト

Java、SAStruts、インターセプターを作る|マコトのおもちゃ箱 ?ぼへぼへ自営業者の技術メモ?

SAStrutsでログイン確認インターセプタを使う – idesaku blog

スポンサーリンク
スポンサーリンク
プログラミング
えふめんをフォローする
この記事が気に入ったら
いいね!しよう
最新情報をお届けします。
俺の開発研究所

コメント

タイトルとURLをコピーしました