3

我创建了一个拦截器,其方法使用 @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 来提取此值。

我查看了 log4j MDC,但我希望避免添加 servlet 过滤器的需要。

4

1 回答 1

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

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

于 2012-11-24T18:31:46.010 回答