我想将任意对象传递给ThreadContext.put()
方法,如下所示:
MyObject originalMessage = new MyObject(...);
ThreadContext.put("originalMessage", originalMessage);
但该方法只允许String
作为其第二个参数:此处为docs。
有没有办法把log4j中的任意对象放在log4j的MDC中?还是其他选择?我想要的是允许log.error()
的进一步执行自动记录originalMessage
,而不需要将其作为参数到处传递。
此外,我自己不能调用toString()
,因为我会急切地评估该方法(在这个对象中这个方法相当重(,所以我希望它的调用被延迟到需要的时候,就像将任意对象传递给log.debug("{}", someObject)
一样。
我终于在这里找到了一个(破解(解决方案。
而不是这个(它不编译(:
ThreadContext.put("originalMessage", originalMessage);
我可以做:
final var threadContextMap = (ObjectThreadContextMap) ThreadContext.getThreadContextMap();
threadContextMap.putValue("originalMessage", originalMessage);
只要您添加以下JVM选项,它就会起作用:
-Dlog4j2.threadContextMap=org.apache.logging.log4j.spi.CopyOnWriteSortedArrayThreadContextMap
现在,这看起来很糟糕,因为getThreadContextMap((方法应该返回内部映射的只读视图:
返回用于存储线程上下文键值对的内部数据结构的只读视图。。。
所以这个解决方案是强制转换只读映射,并且知道实现不是只读的,就修改它。。。不是最透明的解决方案,但它是有效的。