Log4j

log4j Java的日志库。

这个技术已过时,只是很多公司还在用。

log4j2

建议学习 log4j2

快速开始

maven 引入

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

log4j.xml

文件配置信息,放在 resource 文件夹下。

如果没有这个配置文件,log4j 会在启动的时候控制台输出错误提示。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration>

    <!-- 将日志信息输出到控制台 -->
    <appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
        <!-- 设置日志输出的样式 -->
        <layout class="org.apache.log4j.PatternLayout">
            <!-- 设置日志输出的格式 -->
            <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%-5p] [method:%l]%n%m%n%n"/>
        </layout>
    </appender>

    <root>
        <level value="INFO"/>
        <appender-ref ref="ConsoleAppender"/>
    </root>

</log4j:configuration>

入门案例

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

/**
 * @author binbin.hou
 * date 2019/1/28
 */
public class Log4jDemo {

    private static Logger LOGGER = LogManager.getLogger(Log4jDemo.class);

    public static void main(String[]args) {
        LOGGER.debug("[1]-my level is DEBUG");
        LOGGER.info("[2]-my level is INFO");
        LOGGER.warn("[3]-my level is WARN");
        LOGGER.error("[4]-my level is ERROR");
    }

}
  • 日志信息

可见默认的日志级别为 INFO,所以 DEBUG 信息不会被打印。

[2019-01-28 13:26:22:586] [INFO ] [method:Log4jDemo.main(Log4jDemo.java:15)]
[2]-my level is INFO

[2019-01-28 13:26:22:589] [WARN ] [method:Log4jDemo.main(Log4jDemo.java:16)]
[3]-my level is WARN

[2019-01-28 13:26:22:590] [ERROR] [method:Log4jDemo.main(Log4jDemo.java:17)]
[4]-my level is ERROR

web path

在 web 项目中,日志输出时会出现 Log4j 找不到目录的情况。可以考虑将日志输出在项目下。

  • web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

	<!-- 获取项目根路径 -->
	<context-param>  
        <param-name>webAppRootKey</param-name>    
        <param-value>webapp.root</param-value>    
    </context-param> 
    
</web-app>
  • log4j.xml

在这里可以使用 ${webapp.root} 用来获取项目的根目录。

<?xml version="1.0" encoding="UTF-8"?>
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <!-- 记录info日志 -->
    <appender name="infoAppender" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="Encoding" value="UTF-8"/>
        <param name="File" value="${webapp.root}/logs/APP_NAME.log"/>
        <!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 -->
        <param name="Append" value="true"/>
        <param name="DatePattern" value="'.'yyyy-MM-dd'.log'"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %t %p [%c] - %m%n"/>
        </layout>
        <!-- 过滤器设置输出的级别 -->
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="levelMin" value="INFO"/>
            <param name="levelMax" value="ERROR"/>
            <param name="AcceptOnMatch" value="true"/>
        </filter>
    </appender>

    <root>
        <priority value="ALL"/>
        <appender-ref ref="infoAppender"/>
    </root>

</log4j:configuration>

自定义 Layout

应用场景

我们一般使用的 layout,默认是 org.apache.log4j.PatternLayout

如果这个类无法满足我们的需求,我们可以自己定义

简单的例子

我们自己定义了一个属性 prefix,并且在执行默认的 fomart 之后,执行我们的字符串处理。

package layout;

import org.apache.log4j.PatternLayout;
import org.apache.log4j.spi.LoggingEvent;

/**
 * @author binbin.hou
 * date 2019/1/28
 */
public class MyLayout extends PatternLayout {

    /**
     * 自定义参数
     */
    private String prefix;

    @Override
    public String format(LoggingEvent event) {
        String message = super.format(event);
        return prefix+message;
    }

    /**
     * 自定义日志信息处理方法
     * @param message 原始信息
     * @return 处理后的结果
     */
    private String myMessageFomrat(final String message) {
        return prefix+message;
    }

    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

}

如何使用

prefix 是我们自己定义的一个前缀,过会儿我们可以在 log4j.xml 配置使用。

<!-- 设置日志输出的样式 -->
<layout class="org.apache.log4j.PatternLayout">
    <!-- 设置日志输出的格式 -->
    <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%-5p] [method:%l]%n%m%n%n"/>
    <param name="prefix" value="自定义前缀-"/>
</layout>

日志输出

自定义[2019-01-28 13:55:19:400] [INFO ] [method:Log4jDemo.main(Log4jDemo.java:14)]
[2]-my level is INFO

自定义[2019-01-28 13:55:19:404] [WARN ] [method:Log4jDemo.main(Log4jDemo.java:15)]
[3]-my level is WARN

自定义[2019-01-28 13:55:19:404] [ERROR] [method:Log4jDemo.main(Log4jDemo.java:16)]
[4]-my level is ERROR

发现这个字符串已经放在每一个的前面了。

思考

这个简单的功能可以干嘛呢?

可以通过日志对信息进行脱敏。

参考资料

log4j日志扩展—自定义PatternLayout