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メソッドの共通前処理・後処理)
コメント