我使用@AroundInvoke注释的方法创建了一个Interceptor来记录方法调用和相关的时序。这是基于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来提取此值。
我查看了log4j MDC,但我希望避免添加servlet过滤器。
答案 0 :(得分:3)
真的我的问题应该是“如何记录方法调用,以便可以轻松地从日志文件中解析出通过应用程序的给定用户路径?”。现在的问题是假设获得会话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
修改它以将线程重命名为用户名是我做的修改。