正如评论中已经指出的,打印到System.out
这不是一种正确的日志记录方式,并且很难将发送到那里的数据重定向到正确的日志记录框架。
你有两个选择:
System.out 到 JULI 重定向
您可以设置swallowOutput
上下文的属性为 true(参见文档 http://tomcat.apache.org/tomcat-9.0-doc/config/context.html#Common_Attributes),这会将应用程序的标准输出和错误重定向到巨力测井系统 https://tomcat.apache.org/tomcat-9.0-doc/logging.html.
The log4j2-appserver.jar
有一个 JULI 实现,它将所有日志发送到 Log4j2(请参阅文档 https://logging.apache.org/log4j/2.x/log4j-appserver/index.html).
将 System.out 直接重定向到 Log4j
您可以定义PrintStream
to Logger
像这样的适配器:
public class LogPrintStream extends PrintStream {
private static class LogOnFlush extends ByteArrayOutputStream {
// WeakHashMap so that we don't keep a reference to the classloaders.
protected final Map<ClassLoader, Logger> classLoaderLoggers = new WeakHashMap<>();
public LogOnFlush() {
// NOP
}
@Override
public void flush() {
final String message = toString();
if (message != null && message.length() > 0) {
Logger logger = getLogger();
logger.debug(message);
}
reset();
}
public Logger getLogger() {
final ClassLoader cl = Thread.currentThread().getContextClassLoader();
Logger logger = classLoaderLoggers.get(cl);
if (logger == null) {
final String name;
if (cl instanceof WebappClassLoaderBase) {
final WebappClassLoaderBase webCl = (WebappClassLoaderBase) cl;
name = String.format("%s.[%s].[%s]", LogPrintStream.class.getName(), webCl.getHostName(), webCl.getContextName());
} else {
name = String.format("%s.[%08x]", LogPrintStream.class.getName(), cl.hashCode());
}
logger = LogManager.getLogger(name);
classLoaderLoggers.put(cl, logger);
}
return logger;
}
}
public LogPrintStream() {
super(new LogOnFlush(), true);
}
}
并用它来替换System.out
通过System#setOut https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/System.html#setOut(java.io.PrintStream)在服务器启动的早期阶段。你可以,例如用一个LifecycleListener https://tomcat.apache.org/tomcat-9.0-doc/api/org/apache/catalina/LifecycleListener.html像这样:
public class SystemOutReplaceListener implements LifecycleListener {
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (Lifecycle.AFTER_INIT_EVENT.equals(event.getType())) {
System.setOut(new LogPrintStream());
}
}
}
Warning:在此示例中,输出为System.out
被发送到Log4j2。必须小心,以免 Log4j2 将其日志转发到System.out
.