1.简介
Log4j是Log for java的简称,它是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、数据库、GUI组件,甚至是套接口服务器等。我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。而且,这些可以通过一个配置文件灵活地进行配置,而不需要修改应用的代码。
2.Log4j组件构成
Log4j由三个重要的组件构成:
1.日志信息的优先级(Logger)
日志信息的优先级从高到低有ERROR、WARN、INFO、DEBUG,分别用来指定这条日志信息的重要程度
2.日志信息的输出目的地(Appender)
日志信息的输出目的地指定了日志将打印到控制台还是文件中,或者数据库中
3.日志信息的输出格式(Layout)
日志信息的输出格式可以很方便地控制日志信息的显示内容
3.Log4j配置文件格式
Log4j支持两种配置文件格式:
1.XML格式的文件
2.properties格式的文件
当然,我们也可以完全不使用配置文件,而在代码中配置Log4j的环境。但是,使用配置文件会让我们的程序更加灵活。
我们这里主要使用properties格式的文件来进行配置。
4.Log4j定义配置文件
4.1 配置根Logger
在配置文件的开头配置如下:
log4j.rootLogger = [Level],appenderName,appenderName,...
参数说明:
(1)level是日志记录的优先级,分为OFF,FATAL,ERROR,WARN,INFO,DEBUG,ALL
OFF:最高等级,用于关闭所有的日志记录
FATAL:指出每个严重的错误事件将会导致应用程序的退出
ERROR:指出虽然发生错误事件,但仍然不影响系统的继续运行
WARN:表明会出现潜在的错误的情形
INFO:一般用在粗粒度级别上,强调应用程序的运行全程
DEBUG:一般用在粗粒度级别上,强调应用程序的运行全程
ALL:最低等级,用于打开所有日志记录
Log4j建议只使用四个级别,优先级从高到低分别是:ERROR,WARN,INFO,DEBUG。通过在这里定义级别,你可以控制应用程序中相应级别的日志信息的开关。
(2)appenderName指的是日志信息的输出目的地,可以同时指定多个输出目的地。
4.2 配置日志信息输出目的地Appender
Log4j提供的appender有以下几种:
(1)org.apache.log4j.ConsoleAppender — 控制台
(2)org.apache.log4j.FileAppender — 文件
(3)org.apache.log4j.DailyRollingFileAppender — 每天产生一个日志文件
(4)org.apache.log4j.RollingFileAppender — 文件大小达到指定尺寸的时候产生新文件
(5)org.apache.log4j.WriterAppender — 将日志信息以流格式发送到任意指定的地方
配置目的地的语法为:
log4j.appender.appenderName = 完整类名,即上述5种目的地的其中一种
// 然后配置一些参数
log4j.appender.appenderName.optionl = value
...
比如我们要定义一个DEBUG级别的,在控制台输出的Log,则前两步需要这么写:
log4j.rootLogger=DEBUG,stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
4.3 配置日志信息的布局格式
Log4j提供的日志信息的格式Layout有如下几种:
(1)org.apache.log4j.HTMLLayout — 以HTML表格形式布局
(2)org.apache.log4j.PatternLayout — 可以灵活地自定义布局
(3)org.apache.log4j.SimpleLayout — 包含日志信息的级别和消息字符串的简单布局
(4)org.apache.log4j.TTCCLayout — 包含日志产生的时间、线程、类别等等信息
配置日志信息格式的语法为:
log4j.appender.appenderName.layout = 完整的布局类名,即上述4种布局的其中一种
// 配置一些参数
log4j.appender.appenderName.layout.optionl = value
...
如果使用了PatternLayout
,则可以自定义日志格式。Log4j自定义打印格式化日志信息的打印参数如下:
参数 | 解释 |
---|---|
%m | 输出代码中指定的消息 |
%p | 输出优先级,即DEBUG,INFO,WARN,ERROR |
%r | 输出自应用启动到输出该log消息耗费的毫秒数 |
%c | 输出所属的类目,通常就是所在类的全名 |
%t | 输出产生该日志事件的线程名 |
%n | 输出一个回车换行符 |
%d | 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如%d{yyyy-MM-dd HH:mm:ss,SSS} |
%l | 输出日志事件的发生位置,包括类名,发生的线程,以及在代码中的函数 |
%x | 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像Java Servlet这样的多客户多线程的应用中 |
%% | 输出一个”%”字符 |
%F | 输出日志消息产生时所在的文件名称 |
%L | 输出代码中的行号 |
我们也可以通过在百分号%
与模式字符之间加上修饰符来控制其最小宽度,最大宽度和对其方式等,比如
(1)%20c
:指定输出category的名称,最小宽度是20,如果category的名称小于20的话,默认的情况下右对齐
(2)%-20c
:指定输出category的名称,最小宽度是20,如果category的名称小于20的话,“-”号指定左对齐
(3)%.30c
:指定输出category的名称,最大宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格
(4)%20.30c
:如果category的名称小于20就补空格,并且右对齐,如果其名称大于30, 就将左边多出的字符截掉
5.在代码中使用Log4j
在代码中使用Log4j非常简单,首先,我们需要引入Log4j的Jar包,它的下载地址为:【Log4j下载】。
最新的版本为2.6.2(2016年7月30日),不过我的程序中用的是1.2.14版本,所以这里给出的是1.2.14的版本下载链接。【Log4j的1版本和2版本还是有些差别的】
下载zip文件之后解压,找到logging-log4j-1.2.14\logging-log4j-1.2.14\dist\lib\log4j-1.2.14.jar文件,引入到程序即可。
然后,我们需要配置log4j.properties文件,并将这个文件放在src根目录下(默认情况下)。
(1)得到记录器
首先要得到记录器,我们要通过org.apache.log4j.Logger
类中的getLogger()
静态方法,语法:
Logger logger = Logger.getLogger(Class class);
或者
Logger logger = Logger.getLogger(String name);
这里的Class
一般写为this.getClass()
即可。
(2)通过配置文件配置Log4j环境
配置Log4j环境有三种方法:
(1)BasicConfigurator.configure(); --- 自动快速地使用默认的Log4j环境,即这时的log4j.properties文件一定要放在src根目录下
(2)PropertyConfigurator.configure(String configFilename); --- 读取使用Java的特性文件编写的配置文件,要指定文件目录
(3)DOMConfigurator.configure(String fileName); --- 读取XML格式的配置文件
(3)插入记录信息
当上述两个步骤执行完毕后,我们就可以在我们的程序中使用logger来记录日志了。并且我们可以使用不同优先级别的日志记录语句插入到我们想记录日志的任何地方:
logger.debug(Object message);
logger.info(Object message);
logger.warn(Object message);
logger.error(Object message);
而且,要知道的是,Log4j可以记录任何对象,不仅限于字符串,当然,其实Log4j记录的是对象的toString()
方法返回的字符串。
所以,如果是自定义的对象,我们必须实现toString()
方法,否则Log4j记录的会是这个对象内存地址。
6.例子
目录结构如下所示:
(1)其中,log4j.properties的配置文件如下:
log4j.rootLogger=DEBUG,stdout,A,B
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.Threshold = DEBUG
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
log4j.appender.A = org.apache.log4j.DailyRollingFileAppender
log4j.appender.A.File = E://logs/log.html
log4j.appender.A.Append = true
log4j.appender.A.Threshold = DEBUG
log4j.appender.A.layout = org.apache.log4j.HTMLLayout
log4j.appender.B = org.apache.log4j.DailyRollingFileAppender
log4j.appender.B.File = E://logs/error.log
log4j.appender.B.Append = true
log4j.appender.B.Threshold = ERROR
log4j.appender.B.layout = org.apache.log4j.PatternLayout
log4j.appender.B.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
在这个配置文件中,我们定义rootLogger要记录DEBUG级别以上的日志,并且定义了3个Appender,分别为stdout,A和B。
其中stdout
配置的输出目的地是控制台,并且会输出DEBUG级别以上的日志,日志布局方式采用简单的SimpleLayout。
A
配置的输出目的地是一个文件,并且是每天都生成一个新的文件,这个文件指向E://logs/log.html
,那么,当然,它采用的布局方式是HTMLLayout。
B
配置的输出目的地是另一个文件error.log,它只记录ERROR级别以上的日志,并且采用的是自定义的布局。
(2)User类为自定义的类,里面有name和age属性,并实现了toString()
方法:
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
(3)Log类是配置以及测试类
package com.gavin.log4jtest;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class Log {
private Logger logger = Logger.getLogger(this.getClass());
public Logger getLogger() {
return logger;
}
public Log() {
PropertyConfigurator.configure("src/log4j.properties");
}
public static void main(String[] args) {
// 下面的信息将被输出
ArrayList array = new ArrayList<>();
array.add(123);
array.add(345);
array.add(567);
HashMap hm = new HashMap<>();
hm.put("123", 456);
hm.put("43", 456);
hm.put("23", 456);
User user = new User("gavin", 12);
Logger logger = new Log().getLogger();
logger.info("info print by log4j");
logger.warn("warn print by log4j");
logger.error("log error print by log4j");
logger.info(array);
logger.error(hm);
logger.error(user);
}
}
(4)运行结果
【1.控制台的输出】:
【2.E盘的logs文件夹下生成了两个文件log.html和error.log】:
然后我们可以分别打开这两个文件看看:
【3.log.html文件】:
可以看到Log4j为我们直接生成了HTML表格,非常美观。
【4.error.log文件】:
由于我们输出到error.log文件的Appender定义只记录ERROR级别以上的日志,所以这里只有ERROR级别的:
7.拓展
我们也可以将日志记录在数据库,使用Log4j可以很方便地实现。比如我们现在需要将日志记录在SQLServer数据库。
首先我们建立数据库Log4j,并且建表testlog:
create table testlog(
logId int primary key identity(1,1), -- ID号,自增
logDate varchar(45), -- 日志生成时间
thread varchar(45) , -- 当前线程
level varchar(45), -- 日志级别
class varchar(45), -- 生成日志的类
message varchar(500) -- 日志消息
)
接着,我们在log4j.properties中配置输出到数据库的Appender,假设名字为C,如下:
log4j.rootLogger=DEBUG,stdout,A,B,C
# stout,A和B不变,下面是C的定义
log4j.appender.C = org.apache.log4j.jdbc.JDBCAppender
log4j.appender.C.URL = jdbc:sqlserver://localhost:1433;DatabaseName=Log4j
log4j.appender.C.driver = com.microsoft.jdbc.sqlserver.SQLServerDriver
log4j.appender.C.user = 数据库登录用户名
log4j.appender.C.password = 数据库登录密码
log4j.appender.C.Threshold = ERROR
log4j.appender.C.layout = org.apache.log4j.PatternLayout
log4j.appender.C.layout.ConversionPattern = insert into testlog values('%d{yyyy-MM-dd HH:mm:ss}','%t','%-5p','%c','%m')
我们记录在数据库中的信息也是ERROR以上级别的,并且使用自定义的格式将数据插入数据库。
要知道的是这时候程序需要引入连接SQLServer的Jar驱动包,否则是不能连接到数据库的!
引入驱动包后再运行程序,然后看看数据记录到了数据库中: