1.概述

Log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式。日志信息的优先级从高到低ERROR、WARN、 INFO、DEBUG,分别用来指定这条日志信息的重要程度;日志信息的输出目的地指定了日志将打印到控制台还是文件中;而输出格式则控制了日志信息的显 示内容。

2.jar包

log4j-1.2.17.jar

3.定义配置文件

可以完全不使用配置文件,而是在代码中配置Log4j环境。但是,使用配置文件将使您的应用程序更加灵活。Log4j支持两种配置文件格式,一种是XML格式的文件,一种是 properties 文件 (Java特性文件 键=值)。

(1)配置根Logger(rootLogger)

log4j.rootLogger = [ level ] , appenderName, appenderName, …

日志级别(level):

log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。说明:
①级别之间是包含的关系。意思是如果你设置日志级别是trace,则大于等于这个级别的日志都会输出。
②基本上默认的级别没多大区别,就是一个默认的设定。可以通过它的API自己定义级别,也可以随意调用这些方法,不过你要在配置文件里面好好处理了,否则就起不到日志的作用了,而且也不易读,相当于一个规范,你要完全定义一套也可以,不用没多大必要。
③不同的级别含义的简单介绍
- ALL 最低等级的,用于打开所有日志记录。
- TRACE: 是追踪。 designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。
- DEBUG: 出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。
- INFO: 息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。
- WARN:表明会出现潜在错误的情形。有些信息不是错误信息,但是也要给程序员的一些提示,类似于eclipse中代码的验证不是有error 和warn(不算错误但是也请注意,比如以下depressed的方法)。
- ERROR: 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。。
- FATAL: 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了
- OFF : 最高等级,用于关闭所有日志记录。

(2)配置日志信息输出目的地(Appender)

log4j.appender.appenderName = fully.qualified.name.of.appender.class  
log4j.appender.appenderName.option1 = value1  
…  
log4j.appender.appenderName.option = valueN

Log4j提供的appender class有以下几种:

org.apache.log4j.ConsoleAppender   控制台
 org.apache.log4j.FileAppender   文件
 org.apache.log4j.DailyRollingFileAppender   每天产生一个日志文件
 org.apache.log4j.RollingFileAppender   文件大小到达指定尺寸的时候产生一个新的文件
 org.apache.log4j.WriterAppender   将日志信息以流格式发送到任意指定的地方

(3)配置日志信息的格式/布局( Layout)

log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class  
log4j.appender.appenderName.layout.option1 = value1  
…  
log4j.appender.appenderName.layout.option = valueN

①Layout:日志输出格式,Log4j提供的layout有以下几种:

org.apache.log4j.HTMLLayout   以HTML表格形式布局
org.apache.log4j.PatternLayout   可以灵活地指定布局模式
org.apache.log4j.SimpleLayout   包含日志信息的级别和信息字符串
org.apache.log4j.TTCCLayout   包含日志产生的时间、线程、类别等等信息

②Log4J采用类似C语言中的printf函数的打印格式格式化日志信息。打印参数如下:

%m   输出代码中指定的消息
%p   输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r   输出自应用启动到输出该log信息耗费的毫秒数
%c   输出所属的类目,通常就是所在类的全名
%t   输出产生该日志事件的线程名
%n   输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”,也就是一跳消息占用一行
%d   输出日志时间点的日期或时间,紧跟一对花括号进行自定义格式
%c   输出所属的类目,通常就是所在类的全名
%l   精确到行
%x   输出对齐

4.在代码中使用Log4j

(1)得到记录器

 使用Log4j,第一步就是获取日志记录器,这个记录器将负责控制日志信息。其语法为:

public static Logger getLogger( String name)

通过指定的名字获得记录器,如果必要的话,则为这个名字创建一个新的记录器。Name一般取本类的名字,比如:

static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )

(2)读取配置文件

当获得了日志记录器之后,第二步将配置Log4j环境,其语法为:

BasicConfigurator.configure (): 自动快速地使用缺省Log4j环境。  
PropertyConfigurator.configure ( String configFilename) :读取使用properties(Java的特性文件)编写的配置文件。  
DOMConfigurator.configure ( String filename ) :读取XML形式的配置文件。

(3)插入记录信息(格式化日志信息)

第三步使用不同优先级别的日志记录语句插入到想记录日志的任何地方。

Logger.debug(Object message);  
Logger.info(Object message);  
Logger.warn(Object message);  
Logger.error(Object message);

5.案例

(1)案例1:Java Project使用log4j

Java 日志级别实时修改 java -jar 日志级别_java

配置文件log4j.properties

### 设置###
log4j.rootLogger = debug,stdout,D,E

### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 输出DEBUG 级别以上的日志到=D://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = D://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 输出ERROR 级别以上的日志到=D://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =D\://logs/error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern =%-d{yyyy-MM-dd HH\:mm\:ss}  [ %t\:%r ] - [ %p ]  %m%n

MyTest.java

package MyLog4j;
import org.apache.log4j.Logger;
public class MyTest {
    private static Logger logger = Logger.getLogger(MyTest.class.getName()); 
    public static void main(String[] args) {
        // 记录debug级别的信息  
        logger.debug("This is a debug message.");  
        // 记录info级别的信息  
        logger.info("This is a info message.");  
        // 记录error级别的信息  
        logger.error("This is a error message.");  
    }
}

控制台输出

[DEBUG] 2017-02-24 14:12:40,296 method:MyLog4j.MyTest.main(MyTest.java:16)
This is a debug message.
[INFO ] 2017-02-24 14:12:40,298 method:MyLog4j.MyTest.main(MyTest.java:18)
This is a info message.
[ERROR] 2017-02-24 14:12:40,298 method:MyLog4j.MyTest.main(MyTest.java:20)
This is a error message.

文件输出

内容如下,已按照要求输出到对应的文档中去了。

Java 日志级别实时修改 java -jar 日志级别_log4j_02


error.log

2017-02-24 14:37:51  [ main:2 ] - [ ERROR ]  This is a error message.

log.log

2017-02-24 14:37:51  [ main:0 ] - [ DEBUG ]  This is a debug message.
2017-02-24 14:37:51  [ main:1 ] - [ INFO ]  This is a info message.
2017-02-24 14:37:51  [ main:2 ] - [ ERROR ]  This is a error message.

另一种配置方式(java代码配置)

直接在java代码中配置输出的规则,修改MyTest.java代码如下:

package MyLog4j;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class MyTest {
    private static Logger logger = Logger.getLogger(MyTest.class.getName()); 
    public static void main(String[] args) {
        Properties prop = new Properties();
        prop.setProperty("log4j.rootLogger", "DEBUG, CONSOLE");
        prop.setProperty("log4j.appender.CONSOLE", "org.apache.log4j.ConsoleAppender");
        prop.setProperty("log4j.appender.CONSOLE.layout", "org.apache.log4j.PatternLayout");
        prop.setProperty("log4j.appender.CONSOLE.layout.ConversionPattern", "%d{HH:mm:ss,SSS} [%t] %-5p %C{1} : %m%n");
        PropertyConfigurator.configure(prop);
        // 记录debug级别的信息  
        logger.debug("This is a debug message.");  
        // 记录info级别的信息  
        logger.info("This is a info message.");  
        // 记录error级别的信息  
        logger.error("This is a error message.");  
    }
}

控制台输出:

14:41:40,367 [main] DEBUG MyTest : This is a debug message.
14:41:40,368 [main] INFO  MyTest : This is a info message.
14:41:40,368 [main] ERROR MyTest : This is a error message.

(2)案例2:Web Project使用log4j

Java 日志级别实时修改 java -jar 日志级别_log4j_03

log4j.properties

log4j.rootLogger = debug,stdout,D,E  

log4j.appender.stdout = org.apache.log4j.ConsoleAppender  
log4j.appender.stdout.Target = System.out  
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout  
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n  

log4j.appender.D = org.apache.log4j.DailyRollingFileAppender  
log4j.appender.D.File = D://mylog4jlogs/log.log  
log4j.appender.D.Append = true  
log4j.appender.D.Threshold = DEBUG   
log4j.appender.D.layout = org.apache.log4j.PatternLayout  
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n  

log4j.appender.E = org.apache.log4j.DailyRollingFileAppender  
log4j.appender.E.File  D://mylog4jlogs/error.log   
log4j.appender.E.Append = true  
log4j.appender.E.Threshold = ERROR   
log4j.appender.E.layout = org.apache.log4j.PatternLayout  
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

web.xml

<?xml version="1.0" encoding="UTF-8"?>  
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns="http://java.sun.com/xml/ns/javaee"  
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
    id="WebApp_ID" version="3.0">  
    <display-name>MyLog4jWeb</display-name>  

    <servlet>  
        <servlet-name>Log4JTestServlet</servlet-name>  
        <servlet-class>com.now.Log4JTestServlet</servlet-class>  
    </servlet>  

    <!--用来启动 log4jConfigLocation的servlet -->  
    <servlet>  
        <servlet-name>Log4JInitServlet</servlet-name>  
        <servlet-class>com.now.Log4JInitServlet</servlet-class>  
        <init-param>  
            <param-name>log4j-properties-location</param-name>  
            <param-value>/WEB-INF/classes/log4j.properties</param-value>  
        </init-param>  
        <load-on-startup>1</load-on-startup>  
    </servlet>  

    <servlet-mapping>  
        <servlet-name>Log4JTestServlet</servlet-name>  
        <url-pattern>/test</url-pattern>  
    </servlet-mapping>  

  <!-- 设置根目录 -->  
    <context-param>    
        <param-name>webAppRootKey</param-name>    
        <param-value>webapp.root</param-value>    
    </context-param>    

    <context-param>  
        <param-name>log4jConfigLocation</param-name>  
        <param-value>/WEB-INF/classes/log4j.properties</param-value>  
    </context-param>  

</web-app>

Log4JInitServlet.java
web容器一来就初始化的servlet

package com.now;
import java.io.File;  
import java.io.IOException;  
import javax.servlet.ServletConfig;  
import javax.servlet.ServletContext;  
import javax.servlet.ServletException;  
import javax.servlet.annotation.WebServlet;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import org.apache.log4j.BasicConfigurator;  
import org.apache.log4j.PropertyConfigurator;  

@WebServlet("/Log4JInitServlet")  
public class Log4JInitServlet extends HttpServlet {  
    private static final long serialVersionUID = 1L;  

    public Log4JInitServlet() {  
        super();  
    }  

    public void init(ServletConfig config) throws ServletException {  
        System.out.println("Log4JInitServlet 正在初始化 log4j日志设置信息");  
        String log4jLocation = config.getInitParameter("log4j-properties-location");  

        ServletContext sc = config.getServletContext();  

        if (log4jLocation == null) {  
            System.err.println("*** 没有 log4j-properties-location 初始化的文件, 所以使用 BasicConfigurator初始化");  
            BasicConfigurator.configure();  
        } else {  
            String webAppPath = sc.getRealPath("/");  
            String log4jProp = webAppPath + log4jLocation;  
            File yoMamaYesThisSaysYoMama = new File(log4jProp);  
            if (yoMamaYesThisSaysYoMama.exists()) {  
                System.out.println("使用: " + log4jProp+"初始化日志设置信息");  
                PropertyConfigurator.configure(log4jProp);  
            } else {  
                System.err.println("*** " + log4jProp + " 文件没有找到, 所以使用 BasicConfigurator初始化");  
                BasicConfigurator.configure();  
            }  
        }  
        super.init(config);  
    }  

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  

    } 

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  

    }  
}

调用日志Log4JTestServlet,java

package com.now;
import java.io.IOException;  
import javax.servlet.ServletConfig;  
import javax.servlet.ServletException;  
import javax.servlet.annotation.WebServlet;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  

import org.apache.log4j.Logger;  

@WebServlet("/Log4JTestServlet")  
public class Log4JTestServlet extends HttpServlet {  
    private static final long serialVersionUID = 1L;  
    private static Logger logger = Logger.getLogger(Log4JTestServlet.class);    

    public Log4JTestServlet() {  
        super();  
    }  

    public void init(ServletConfig config) throws ServletException {  
    }  

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
        // 记录debug级别的信息    
        logger.debug("This is a debug message.");    
        // 记录info级别的信息    
        logger.info("This is a info message.");    
        // 记录error级别的信息    
        logger.error("This is a error message.");    
    }  

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
        doGet(request,response);  
    }  

}

启动tomcat运行, 浏览器输入http://localhost:8080/MyLog4jWeb/Log4JTestServlet:

Java 日志级别实时修改 java -jar 日志级别_Java 日志级别实时修改_04

(3)案例3:Spring 使用log4j

Java 日志级别实时修改 java -jar 日志级别_java_05

导入Spring的包

导入spring所需要的所有jar包

web.xml
<?xml version="1.0" encoding="UTF-8"?>  
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns="http://java.sun.com/xml/ns/javaee"  
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
    id="WebApp_ID" version="3.0">  
    <display-name>LogLearning</display-name>  

    <servlet>  
        <servlet-name>Log4JTestServlet</servlet-name>  
        <servlet-class>com.now.Log4JTestServlet</servlet-class>  
    </servlet>  

    <!--用来启动 log4jConfigLocation的servlet -->  
    <servlet>  
        <servlet-name>Log4JInitServlet</servlet-name>  
        <servlet-class>com.now.Log4JInitServlet</servlet-class>  
        <init-param>  
            <param-name>log4j-properties-location</param-name>  
            <param-value>/WEB-INF/classes/log4j.properties</param-value>  
        </init-param>  
        <load-on-startup>1</load-on-startup>  
    </servlet>  

    <servlet-mapping>  
        <servlet-name>Log4JTestServlet</servlet-name>  
        <url-pattern>/test</url-pattern>  
    </servlet-mapping>  

     <!-- Spring 容器加载 -->  
    <listener>  
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
    </listener>  
    <context-param>  
        <param-name>contextConfigLocation</param-name>  
        <param-value>classpath:applicationContext.xml</param-value>  
    </context-param>    
  <!-- 设置根目录 -->  
    <context-param>    
        <param-name>webAppRootKey</param-name>    
        <param-value>webapp.root</param-value>    
    </context-param>    

    <context-param>  
        <param-name>log4jConfigLocation</param-name>  
        <param-value>/WEB-INF/classes/log4j.properties</param-value>  
    </context-param>  
    <!-- 3000表示 开一条watchdog线程每60秒扫描一下配置文件的变化;这样便于日志存放位置的改变 -->  
    <context-param>    
            <param-name>log4jRefreshInterval</param-name>    
            <param-value>3000</param-value>    
       </context-param>   
    <listener>  
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>  
    </listener>
</web-app>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xsi:schemaLocation="    
           http://www.springframework.org/schema/beans    
           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd    
           http://www.springframework.org/schema/aop    
           http://www.springframework.org/schema/aop/spring-aop-3.2.xsd  
           http://www.springframework.org/schema/context    
           http://www.springframework.org/schema/context/spring-context-3.2.xsd">  
</beans>
启动服务器运行结果:

Java 日志级别实时修改 java -jar 日志级别_java日志组件_06

6.总结

Logger类:完成日志记录,设置日志信息级别
Appender类:决定日志去向,终端、DB、硬盘
Layout类:决定日志输出的样式,例如包含当前线程、行号、时间