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

时间:2012-11-21 10:28:22

标签: java logging java-ee-6 cdi interceptor

我使用@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过滤器。

1 个答案:

答案 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

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