将System.out和System.err重定向到slf4j

我需要将System.out / err.println输出重定向到slf4j。

我知道这不是正确记录的方法,但有一个外部库,它记录到System.out

您可以使用sysout-over-slf4j 。

sysout-over-slf4j模块允许用户将对System.out和System.err的所有调用重定向到SLF4J定义的记录器,该记录器具有完全限定类的名称,在该类中进行System.out.println(或类似)调用,在可配置的级别。

如果您没有使用Maven,请下载 jar并将其添加到类路径中。

或者,将其添加为Maven依赖项:

 uk.org.lidalia sysout-over-slf4j 1.0.2  

然后在应用程序启动时, 调用 :

 SysOutOverSLF4J.sendSystemOutAndErrToSLF4J(); 

我通过使用LoggingOutputStream for log4j解决了这个问题,并为slf4j稍微修改了一下。

 import java.io.IOException; import java.io.PrintStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SysStreamsLogger { private static Logger sysOutLogger = LoggerFactory.getLogger("SYSOUT"); private static Logger sysErrLogger = LoggerFactory.getLogger("SYSERR"); public static final PrintStream sysout = System.out; public static final PrintStream syserr = System.err; protected static final String LINE_SEPERATOR = System.getProperty("line.separator"); public static void bindSystemStreams() { // Enable autoflush System.setOut(new PrintStream(new LoggingOutputStream(sysOutLogger, false), true)); System.setErr(new PrintStream(new LoggingOutputStream(sysErrLogger, true), true)); } public static void unbindSystemStreams() { System.setOut(sysout); System.setErr(syserr); } private static class LoggingOutputStream extends java.io.OutputStream { protected Logger log; protected boolean isError; /** * Used to maintain the contract of {@link #close()}. */ protected boolean hasBeenClosed = false; /** * The internal buffer where data is stored. */ protected byte[] buf; /** * The number of valid bytes in the buffer. This value is always in the * range 0 through buf.length; elements * buf[0] through buf[count-1] contain valid byte * data. */ protected int count; /** * Remembers the size of the buffer for speed. */ private int bufLength; /** * The default number of bytes in the buffer. =2048 */ public static final int DEFAULT_BUFFER_LENGTH = 2048; private LoggingOutputStream() { // illegal } /** * Creates the LoggingOutputStream to flush to the given Category. * * @param log * the Logger to write to * * @param isError * the if true write to error, else info * * @exception IllegalArgumentException * if cat == null or priority == null */ public LoggingOutputStream(Logger log, boolean isError) throws IllegalArgumentException { if (log == null) { throw new IllegalArgumentException("log == null"); } this.isError = isError; this.log = log; bufLength = DEFAULT_BUFFER_LENGTH; buf = new byte[DEFAULT_BUFFER_LENGTH]; count = 0; } /** * Closes this output stream and releases any system resources * associated with this stream. The general contract of * close is that it closes the output stream. A closed * stream cannot perform output operations and cannot be reopened. */ @Override public void close() { flush(); hasBeenClosed = true; } /** * Writes the specified byte to this output stream. The general contract * for write is that one byte is written to the output * stream. The byte to be written is the eight low-order bits of the * argument b. The 24 high-order bits of b are * ignored. * * @param b * the byte to write */ @Override public void write(final int b) throws IOException { if (hasBeenClosed) { throw new IOException("The stream has been closed."); } // don't log nulls if (b == 0) { return; } // would this be writing past the buffer? if (count == bufLength) { // grow the buffer final int newBufLength = bufLength + DEFAULT_BUFFER_LENGTH; final byte[] newBuf = new byte[newBufLength]; System.arraycopy(buf, 0, newBuf, 0, bufLength); buf = newBuf; bufLength = newBufLength; } buf[count] = (byte) b; count++; } /** * Flushes this output stream and forces any buffered output bytes to be * written out. The general contract of flush is that * calling it is an indication that, if any bytes previously written * have been buffered by the implementation of the output stream, such * bytes should immediately be written to their intended destination. */ @Override public void flush() { if (count == 0) { return; } // don't print out blank lines; flushing from PrintStream puts out // these if (count == LINE_SEPERATOR.length()) { if (((char) buf[0]) == LINE_SEPERATOR.charAt(0) && ((count == 1) || // <- // Unix // & // Mac, // -> // Windows ((count == 2) && ((char) buf[1]) == LINE_SEPERATOR.charAt(1)))) { reset(); return; } } final byte[] theBytes = new byte[count]; System.arraycopy(buf, 0, theBytes, 0, count); if (isError) { log.error(new String(theBytes)); } else { log.info(new String(theBytes)); } reset(); } private void reset() { // not resetting the buffer -- assuming that if it grew that it // will likely grow similarly again count = 0; } } } 

现在,可以通过在应用程序开始时调用SysStreamsLogger.bindSystemStreams()来重定向Sytem.out / err。

记录输出如下(来自OpenEJB启动)

 2012-06-27 13:44:12,792 INFO [main:] SYSOUT:181 - Apache OpenEJB 3.1.4 build: 20101112-03:32 2012-06-27 13:44:12,793 INFO [main:] SYSOUT:181 - http://openejb.apache.org/