Interceptor為攔截器,可以監聽程序的整個程序或方法。從多個程序理解問題往往比較容易,我就在自己寫的HelloWorld 程序的基礎上增加了Interceptor .
有如下幾個程序:Hello.java , HelloLocal.java , HelloRemote.java , HelloBean.java, TracingInterceptor.Java
ClIEnt.Java
重點在HelloBean.java, TracingInterceptor.Java 這兩個程序。
Hello.Java
/**
* @author roson
*
* 2005-4-10
*/
package org.jboss.tutorial.stateless.bean;
public interface Hello {
public void hello();
public String hello2();
}
HelloLocal.Java
/**
* @author roson
*
* 2005-4-10
*/
package org.jboss.tutorial.stateless.bean;
import Javax.ejb.Local;
@Local
public interface HelloLocal extends Hello{
}
HelloRemote.Java
/**
* @author roson
*
* 2005-4-10
*/
package org.jboss.tutorial.stateless.bean;
import Javax.ejb.Remote;
@Remote
public interface HelloRemote extends Hello{
}
HelloBean.Java
/**
* @author roson
*
* 2005-4-10
*/
package org.jboss.tutorial.stateless.bean;
import Javax.ejb.InvocationContext;
import Javax.ejb.Stateless;
import Javax.ejb.AroundInvoke;
import Javax.ejb.Interceptor;
@Stateless
@Interceptor("org.jboss.tutorial.stateless.bean.TracingInterceptor")
public class HelloBean implements HelloRemote,HelloLocal {
public void hello()
{
System.out.println("Hello roson");
}
public String hello2()
{
return "are you ok";
}
@AroundInvoke
public Object myBeanInterceptor(InvocationContext ctx) throws Exception
{
if (ctx.getMethod().getName().equals("hello"))
{
System.out.println("*** hello: " );
}
if (ctx.getMethod().getName().equals("hello2"))
{
System.out.println("*** hello2: " );
}
return ctx.proceed();
}
}
說明:
@Interceptor("org.jboss.tutorial.stateless.bean.TracingInterceptor") 定義了一個自己定義的Interceptor 。
也可以有多個 Interceptor 格式如下
@Interceptors ({"org.jboss.TracingInterceptor", "org.jboss..OtherInterceptor"})
以上兩種監視整個class的情況,要做的更細點就是單獨監視攔截每個方法,需要另外寫個方法:
@AroundInvoke
public Object 方法名可以任意(InvocationContext ctx) throws Exception
{
}
TracingInterceptor.Java
package org.jboss.tutorial.stateless.bean;
import Javax.ejb.AroundInvoke;
import Javax.ejb.InvocationContext;
public class TracingInterceptor {
@AroundInvoke
public Object log(InvocationContext ctx) throws Exception
{
System.out.println("*** TracingInterceptor intercepting");
long start = System.currentTimeMillis();
try
{
return ctx.proceed();
}
catch(Exception e)
{
throw e;
}
finally
{
long time = System.currentTimeMillis() - start;
String method = ctx.getBean().getClass().getName() + "." + ctx.getMethod().getName() + "()";
System.out.println("*** TracingInterceptor invocation of " + method + " took " + time + "ms");
}
}
}
這是在jboss-EJB-3.0_PrevIEw_5.zip中的一個Interceptor ,可以參照這個Interceptor寫噢。
ClIEnt.Java
package org.jboss.tutorial.stateless.clIEnt;
import org.jboss.tutorial.stateless.bean.Calculator;
import org.jboss.tutorial.stateless.bean.Hello;
import org.jboss.tutorial.stateless.bean.HelloRemote;
import Javax.naming.InitialContext;
public class ClIEnt
{
public static void main(String[] args) throws Exception
{
InitialContext ctx = new InitialContext();
Hello hello=(Hello)ctx.lookup(HelloRemote.class.getName());
hello.hello();
System.out.println(hello.hello2());
}
}
在客戶端程序裡居然毫無Interceptor 的蹤跡,呵呵。這裡需要指出的是 hello ,hello2 方法輸出的地方是不同的,一個在build ant 的窗口,另一個是在 jboss 運行窗口。
這裡附上log4j.properties 在jboss-EJB-3.0_PrevIEw_5.zip 裡面沒有這個老是顯示缺少appender。有了這個將在該目錄下生成個record.log日志文件。
log4j.propertIEs
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=record.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %d{hh:mm:ss} %t %c{1} -%m%n
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.MaxFileSize=100KB
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) -%m%n
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.rootLogger=stdout,R
運行:參考installing.Html
要運行這個程序可以把它與jboss-EJB-3.0_PrevIEw_5.zip裡的相結合,更改下build.XML文件裡的 target run就行了.
Windows下
打開命令提示符cmd,到 jboss_home/bin
Run.bat –c all
用ant
先build後run 就行了。
討論:
在很多地方可以看到 Interceptor的身影,我最先是在aop 那裡見到的。jboss-EJB-3.0_PrevIEw_5.zip 裡面的Interceptor的例子可能是為了結合前面所學的,把一些知識綜合起來了。也不是很難理解,這裡我只是把它分解了,更容易察看和掌握。