通过 javax 拦截器记录用户的会话标识



我创建了一个Interceptor,其中包含一个用@AroundInvoke注释的方法,用于记录方法调用和相关的计时。这是基于Richard Hightowers在CDI AOP上出色的博客文章http://java.dzone.com/articles/cdi-aop):

@AroundInvoke
public Object log(InvocationContext ctx) throws Exception {
Logger logger = Logger.getLogger(ctx.getTarget().getClass().getName());
logger.trace("ENTERING : "+ctx.getMethod());
long start = System.currentTimeMillis();
Object returnMe = ctx.proceed();
long executionTime = System.currentTimeMillis() - start;
logger.trace("EXITING : "+ctx.getMethod()+":"+executionTime+"ms");
return returnMe;
}

我想记录用户的会话id,这样我就可以很容易地分析用户通过应用程序的路径。如何获取用户的会话?

我研究了注入SessionContext,但看不出如何使用API来提取这个值。

我已经看过log4jMDC,但我希望避免添加servlet过滤器的需要。

实际上,我的问题应该是"如何记录方法调用,以便可以轻松地从日志文件中解析出应用程序中的给定用户路径?"。目前的问题假设获得会话id是答案,但事实可能并非如此。考虑到这个措辞更好的问题,我现在发现,只要所有关注的业务逻辑都是通过EJB访问的,你就可以按照如下方式记录给定的用户路径:

创建一个注入EJB SessionContext的拦截器类:

/**
* SessionContext of this EJB; this will be injected by the EJB
* Container because it's marked w/ @Resource
*/
@Resource
private SessionContext context;

添加一个用AroundInvoke注释的方法,该方法将拦截调用:

@AroundInvoke
public Object log(InvocationContext ctx) throws Exception {
String originName = Thread.currentThread().getName();
String currentUser = context.getCallerPrincipal().getName();
try{
String tracingName = currentUser + " " + originName;
Thread.currentThread().setName(tracingName);
return ctx.proceed();
}finally{
Thread.currentThread().setName(originName);
}
}

请注意,我们使用会话上下文来获取导致此操作的用户。然后,我们更改线程的名称以保存该用户名。该调用堆栈中的所有后续日志记录都将输出用户名,假设loggin被配置为也输出线程名称,而不管它们是在EJB中还是只是某个POJO类中。

这个线程重命名的灵感来自Adam Bien的独立于服务器的线程跟踪实用程序:

http://www.adam-bien.com/roller/abien/entry/server_independent_thread_tracking_utility

修改它以将线程重命名为用户名是我所做的修改。

最新更新