现在,我的同事正在研究日志记录子系统,他们希望绑定从某些业务方法启动的单独操作。例如,如果来自bean A的方法调用bean B中的某个方法,然后在bean C中调用bean,那么知道比bean B中的业务方法更好,并且bean C为Bean A中的方法做了一些工作。特别是它会很棒知道B和C的方法完成了一些工作单元的具体调用bean。
那么,问题是如何将这些工作单元整合到一起?显然,使用方法参数进行绑定并不漂亮!
而且我认为现在是时候提出另一个问题,这个问题与前一个问题相近。如果我想将一些上下文信息从bean A传播到另一个从A调用的bean,该怎么办?安全凭证和安全主体之类的东西?我能做什么? 可能是我问的问题是某种不良做法?
答案 0 :(得分:3)
看起来是mdc的一个很好的用例,Logback和Log4J都可用。基本上,您将一些自定义值附加到一个线程,并且来自该线程的所有日志消息都可以将该值附加到该消息。
我认为在EJB中实现它的最佳方法是interceptor:
public class MdcInterceptor {
@AroundInvoke
public Object addMdcValue(InvocationContext context) throws Exception {
MDC.put("cid", RandomStringUtils.randomAlphanumeric(16));
try {
return context.proceed();
} finaly {
MDC.remove("cid");
}
}
}
现在你需要做的就是添加:
%X{user}
到您的记录模式(logback.xml
或log4j.xml
)。
答案 1 :(得分:0)
对于通用上下文信息,您可以使用TransactionSynchronizationRegistry。它可能看起来像这样:
@Stateless
public class MyBean {
@Resource
TransactionSynchronizationRegistry registry;
@AroundInvoke
public Object setEntryName(InvocationContext ic) throws Exception {
registry.putResource(NAME, "MyBean");
return ic.proceed();
}
}
@Stateless
public class MyBean2 {
@Resource
TransactionSynchronizationRegistry registry;
public void doJob() {
String entryName = (String)registry.getResource(NAME);
...
}
}
我相信它通常使用ThreadLocal变量实现,因为通常每个事务都映射到应用程序服务器中的sigle线程。因此,如果您的AS中没有实现TransactionSynchronizationRegistry(例如在JBoss 4.2.3中),或者您需要较低级别的工具,则可以直接使用ThreadLocal变量。
BTW我想MDC实用程序使用相同的东西。