インターセプタを作るためには「com.opensymphony.xwork2.interceptor.Interceptor」を実装しなければならない。
Interceptorインタフェース
以下の3メソッドが定義されている。
- void destroy()
- void init()
- String intercept(ActionInvocation invocation)
- initメソッド
- インターセプターがインスタンス化された後に呼び出される。インターセプターの初期化に使える。
- interceptメソッド
- ここにインターセプタの処理を実装する。メソッドは、Strutsで使う他のWebリソースへリクエストをforwardする結果を返す。
- destroyメソッド
- アプリケーション停止時にリソースのリリースを行う。
インターセプタはスレッドセーフでなければならない。
AbstractInterceptor
AbstractInterceptorはinitメソッドとdestroyメソッドの空の実装を提供する。これをつかえば2メソッドを実装しなくてもよくなる。
開始/終了ログ出力インターセプタを作ってみる
Actionの開始、終了時にログを出力するインターセプタを作成する。LoggingInterceptorがあるけど、自分で用意したほうがカスタマイズが楽そう。
インターセプタクラスの作成
AbstractInterceptorを継承して作成した。Action終了時にも呼び出したいので、PreResultListenerをaddしている。これをしないと終了時に動いてくれない。
//AbstractInterceptor.java
public class ActionLoggingInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("[開始]" + invocation.getAction().getClass().getSimpleName());
//後処理用
invocation.addPreResultListener(new PreResultListener() {
public void beforeResult(ActionInvocation invocation, String result) {
System.out.println("[終了][" + result + "]" + invocation.getAction().getClass().getSimpleName());
}
});
return invocation.invoke();
}
}
struts.xmlの修正
actionLoggingStackを定義してその中で上記クラスを呼び出す設定を行う。たいていの場合、defaultStackを最後に呼び出す。呼び出さないとvaliadtorなどが動いてくれない。
//struts.xml
<interceptors>
<interceptor name="actionlogging" class="com.daipresents.struts209.interceptor.ActionLoggingInterceptor"/>
<interceptor-stack name="actionLoggingStack">
<interceptor-ref name="actionlogging"/>
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>
<action name="userreg"
class="com.daipresents.struts209.action.UserRegAction">
<interceptor-ref name="actionLoggingStack"/>
<result name="success">/WEB-INF/jsp/complete.jsp</result>
<result name="input">/WEB-INF/jsp/userreg.jsp</result>
<result name="error">/WEB-INF/jsp/userreg.jsp</result>
</action>
実行結果
実行すると以下のようにコンソールに出力された。
[開始]UserRegAction
2007/10/19 18:40:06 com.opensymphony.xwork2.validator.ActionValidatorManagerFactory <clinit>
情報: Detected AnnotationActionValidatorManager, initializing it...
[終了][input]UserRegAction
その他の動作
Interceptorsを調べてみると、Webアプリケーションのアーキテクチャとして役に立ちそうなものがたくさんある。これは本当に便利な仕組みに見える。
例外が発生したときやValidatorに引っかかったときはどうなるのかを調べてみると
//Validatorに引っかかったときのログ
[開始]UserRegAction
[終了][input]UserRegAction
//例外が発生したときのログ(catchせず)
[開始]UserRegAction
2007/10/22 11:35:19 org.apache.catalina.core.StandardWrapperValve invoke
致命的: サーブレット default のServlet.service()が例外を投げました
java.lang.Exception: 例外が発生しました
となっている。Validatorの場合もちゃんと終了ログがでるのがいい。例外発生時はログが出なかったけど、例外捕捉Interceptorもあるから、そこできちんと対応すれば出る気がする。