我不相信這些說明是可以接受的Web應用程序。整個Web服務器/ Servlet容器都有一個JUL。
如果您使用BIRT API生成報告,BIRT允許您設置自己的記錄器。請參閱EngineConfig.setLogger()方法。它至少在BIRT 4.3.1中起作用。我們做如下(重定向BIRT日誌SLF4J,但這個想法應該是Log4J的相同):
EngineConfig config = new EngineConfig();
// set logger that forwards log messages to SLF4J
// as of BIRT 4.3.1 the custom logger will be accepted only if it or one of its parent in the BIRT's root logger list.
// see http://git.eclipse.org/c/birt/org.eclipse.birt.git/commit/engine/org.eclipse.birt.report.engine/src/org/eclipse/birt/report/engine/api/impl/EngineLogger.java?h=Kepler&id=1cb9507c8ce997bf5407a73d9c23487cef002fa9
java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger("org.eclipse.birt" + ".myapp.Slf4jBridge");
julLogger.setUseParentHandlers(false);
Handler logHandler = new Slf4jLogHandler();
logHandler.setLevel(Level.FINEST);
julLogger.addHandler(logHandler);
config.setLogger(julLogger);
而且Slf4jLogHandler執行如下:
public class Slf4jLogHandler extends Handler {
private Formatter julFormatter = new SimpleJulFormatter();
@Override
public void publish(LogRecord record) {
if (record == null) {
return;
}
ClassLoader hanlderClassLoader = this.getClass().getClassLoader();
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if (hanlderClassLoader != contextClassLoader) {
// do not log in foreign contexts
/*
* This check is necessary if several web applications with "JUL to SLF4J" bridge are deployed in the same Servlet container.
* Each application has its own instance of SLF4J logger, but they all are mapped to the same JUL logger,
* because the JUL logger is loaded by the root classloader. Whereas SLF4J loggers are loaded by their respective
* webapp classloaders. Thus comparing classloaders is the only known way to find out whom the JUL log record belongs to.
*/
return;
}
String loggerName = record.getLoggerName();
if (loggerName == null) {
loggerName = "unknown";
}
Logger slf4jLogger = LoggerFactory.getLogger(loggerName);
/*
* JUL levels in descending order are:
* <ul>
* <li>SEVERE (highest value)
* <li>WARNING
* <li>INFO
* <li>CONFIG
* <li>FINE
* <li>FINER
* <li>FINEST (lowest value)
* </ul>
*/
if (record.getLevel().intValue() <= Level.FINEST.intValue()) {
if (slf4jLogger.isTraceEnabled()) {
slf4jLogger.trace(julFormatter.format(record), record.getThrown());
}
} else if (record.getLevel().intValue() <= Level.FINE.intValue()) {
if (slf4jLogger.isDebugEnabled()) {
slf4jLogger.debug(julFormatter.format(record), record.getThrown());
}
} else if (record.getLevel().intValue() <= Level.INFO.intValue()) {
if (slf4jLogger.isInfoEnabled()) {
slf4jLogger.info(julFormatter.format(record), record.getThrown());
}
} else if (record.getLevel().intValue() <= Level.WARNING.intValue()) {
if (slf4jLogger.isWarnEnabled()) {
slf4jLogger.warn(julFormatter.format(record), record.getThrown());
}
} else if (record.getLevel().intValue() <= Level.SEVERE.intValue()) {
if (slf4jLogger.isErrorEnabled()) {
slf4jLogger.error(julFormatter.format(record), record.getThrown());
}
} else if (record.getLevel().intValue() == Level.OFF.intValue()) {
// logger is switched off
} else {
slf4jLogger.warn("Unexpected log level {}.", record.getLevel().intValue());
if (slf4jLogger.isErrorEnabled()) {
slf4jLogger.error(julFormatter.format(record), record.getThrown());
}
}
}
@Override
public void flush() {
// noop
}
@Override
public void close() throws SecurityException {
// noop
}
}
這種方法適用即使有幾個Web應用程序在同一臺服務器上使用BIRT。
你自己寫了'Slf4jLogHandler'而不是使用SLF4J'org.slf4j.bridge.SLF4JBridgeHandler'的原因是什麼?是否按照代碼註釋或其他內容在外部環境中進行登錄? – Barney