把在程序中的System.out.print()的信息自动转成log4j日志信息

问题:老的系统中,程序未使用log4j,而是使用System.out.println()将信息打印到了tomcat。现在客户提出要保存打印到tomcat的日志信息,引入log4j固然需要,但修改代码及后续测试的工作量与风险也让人头大。如何解决这样的问题呢?

回答:System.setOut(PrintStream ps)方法允许程序员自行定义System.out输出流,我们可以将我们改造好的PrintStream替换java原来的System.out对象。

为了能在web服务器启动以后完成这个替换的过程,我们定义一个ServletContextListener监听器,在web服务器启动时完成替换。

package com;

import java.io.PrintStream;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.logging.impl.LogFactoryImpl;
/**
* 把在程序中的System.out.print()的信息自动转成日志信息
*/
public class StdoutListener implements ServletContextListener {
    public void contextDestroyed(ServletContextEvent event) {
    }
    private void log(Object info) {
        LogFactoryImpl.getLog(getClass()).info(info);
    }
    public void contextInitialized(ServletContextEvent event) {
        PrintStream printStream = new PrintStream(System.out) {
            public void println(boolean x) {
                log(Boolean.valueOf(x));
            }
            public void println(char x) {
                log(Character.valueOf(x));
            }
            public void println(char[] x) {
                log(x == null ? null : new String(x));
            }
            public void println(double x) {
                log(Double.valueOf(x));
            }
            public void println(float x) {
                log(Float.valueOf(x));
            }
            public void println(int x) {
                log(Integer.valueOf(x));
            }
            public void println(long x) {
                log(x);
            }
            public void println(Object x) {
                log(x);
            }
            public void println(String x) {
                log(x);
            }
        };
        System.setOut(printStream);
        System.setErr(printStream);
    }
}

在web.xml里配置这个监听器,完善log4j.properties文件。搞定!

附:

web.xml中配置监听器:

<listener>
<listener-class>com.bettersoft.filters.StdoutListener</listener-class>

</listener>

我的 log4j.properties文件:

log4j.rootLogger=INFO,Stdout,R
log4j.appender.Stdout=org.apache.log4j.ConsoleAppender
log4j.appender.Stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.Stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %m%n
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=../logs/stdout.log
log4j.appender.R.datePattern='.'yyyy-MM-dd'.txt'
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %m%n

说明:

log4j.rootLogger=INFO,Stdout,R  指定INFO及以上级别的日志会被输出到Stdout 和 R 两个终端

log4j.appender.Stdout=org.apache.log4j.ConsoleAppender 输出到控制台

log4j.appender.R=org.apache.log4j.DailyRollingFileAppender 指定了每天产出一个日志文件(R是自定义的)。

log4j.appender.R.File=../logs/stdout.log 指定了日志文件的路径和文件名,这样配置以后,我的日志文件就在D:\tomcat5\logs目录下。

log4j.appender.R.datePattern='.'yyyy-MM-dd'.txt' 指定了日志文件名的格式,比如8月6日的文件名就是stdout.log.2011-08-06.txt。

                                                         经过测试发现,当天的日志会被暂存在名为 stdout.log的日志文件中,只有日期更迭以后才会自动变更为符合

                                                         格式的文件名。

续:

经过试验, 如果在tomcat下有两个应用A和B,A如上述一般配置,B中未配置,但B的lib中有log4j的jar包,那么在tomcat启动时可能会报一个堆栈溢出的异常。

原因是在tomcat启动时,B程序中的log4j包会用到System.out.println(),而这个System.out.println()会被A的StdoutListener监听到而引发死循环调用。至于为什么A中的监听器会监听到B中的调用,还不清楚。

暂时的解决办法:在B中也做上述配置,引入StdoutListener,编写log4j.properties。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值