文章目录
- 一、学习目标
- 二、学习笔记
- 2.1 JUL学习
- 2.1.1 架构介绍
- 2.1.2 JUL执行原理
- 2.1.3 JUL硬编码配置
- 2.1.4 Logger对象的父子关系
- 2.1.5 JUL配置文件
- 2.2 Log4j学习
- 2.2.1 Layout日志信息格式
- 2.2.2 appender
- 2.2.2.1 ConsoleAppender配置
- 2.2.2.2 FileAppender配置
- 2.2.2.3 RollingFileAppender配置
- 2.2.2.4 DailyRollingFileAppender配置
- 2.2.3 Layouts
- 2.2.4 Layout的格式
- 2.2.5 自定义logger
- 2.3 JCL学习(淘汰)
- 2.4 Slf4j 学习
- 2.4.1 slf4j + log4j
- 2.5 logback学习
- 学习产出:
一、学习目标
1、了解java常用日志框架
2、掌握JUL(java util logging)
3、掌握Log4j和Log4j2
4、掌握JCL(jakarta Commons Logging)
5、掌握slf4j(Simple Logging Facade for Java)
6、各种日志框架使用场景
二、学习笔记
2.1 JUL学习
JUL全称Java util Logging是java原生的日志框架,使用时不需要另外引入第三方类库,相对其他日志框架使用方便,学习简单,能够在小型应用中灵活使用。
2.1.1 架构介绍
- Loggers
被称为记录器,应用程序通过获取Logger对象,调用其API来发布日志信息。Logger通常是应用程序访问日志系统的入口程序。 - Appender
被称为Handler,每个Logger都会关联一组Handlers,Logger会将日志交给关联Handlers处理,有Handler负责将日志做记录。Handler是一个抽象,其具体实现决定了日志的位置可以是控制台、文件、网络上的其他日志服务或者操作系统日志等。 - Layouts
被称为Formatters,它负责对日志事件中的数据进行转换和格式化。Layouts决定了数据在一条日志记录中的最终形式。 - Level
每条日志消息都有一个关联的日志级别。该级别粗略知道了日志消息的重要性和紧迫性,可以将Level和Loggers,Appenders做关联以便我们过滤消息。 - Filters
过滤器,根据需要定制那些信息会被记录,那些信息被放弃
2.1.2 JUL执行原理
1、初始化LogManager
(1)LogManager加载logging.properties配置
(2)添加Logger到LogManager
2、从单例LogManager获取Logger
3、设置级别Level,并指定日志记录LogRecord
4、Filter提供了日志级别之外更细粒度的控制
5、Handler是用来处理日志输出位置
6、Formatter用来格式化LogRecord的
2.1.3 JUL硬编码配置
jdk自带的日志记录器,不需要额外引入依赖,在rt.jar中:
一共有七个日志级别
public class JulTest {
public static void main(String[] args) throws IOException {
Logger logger = Logger.getLogger(JulTest.class.getName());
//关闭系统默认配置
logger.setUseParentHandlers( false );
//自定义配置日志级别
//创建ConsolHhandler
ConsoleHandler consoleHandler = new ConsoleHandler();
//创建简单格式转换对象
SimpleFormatter simpleFormatter = new SimpleFormatter();
//进行关联
consoleHandler.setFormatter(simpleFormatter);
logger.addHandler( consoleHandler );
//设置日志级别
logger.setLevel(Level.ALL); //logger进行第一个日志级别过滤
consoleHandler.setLevel(Level.CONFIG); //handler进行第二次日志级别的过滤
//添加文件类型的输出,
//入参:pattern(文件路径);append(是否在原文件追加日志,false代表每次覆盖文件)
FileHandler fileHandler = new FileHandler("d:/jul.log",true);
//多个文件循环覆盖,如下为:10个文件,每个文件最大1M
//FileHandler fileHandler1 = new FileHandler("d:/jul.log",1024*1024,10);
fileHandler.setFormatter(simpleFormatter);
//添加文件日志处理器
logger.addHandler(fileHandler);
//设置日志级别
logger.setLevel(Level.ALL);
fileHandler.setLevel(Level.ALL);
//测试
logger.severe("测试severe");
logger.warning("测试warning");
logger.info("测试info");
logger.config("测试config");
logger.fine("测试fine");
logger.finer("测试finer");
logger.finest("测试finest");
}
}
2.1.4 Logger对象的父子关系
@Test
public void loggerParentSon() {
Logger logger = Logger.getLogger("com.cmb.jultest");
Logger logger1 = Logger.getLogger("com.cmb");
//输出结果为true
System.out.println(logger.getParent() == logger1) ;
//
//获取logger1的父对象
//所有日志记录器的顶级父元素 LogManager$RootLogger,name 为 "";
System.out.println("logger1的Parent:" + logger1.getParent() + ",loggerName:" + logger1.getParent().getName());
}
2.1.5 JUL配置文件
1、默认配置文件在jdk目录下:\Program Files\Java\jdk1.8.0_211\jre\lib\logging.properties
############################################################
# Default Logging Configuration File
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property.
# For example java -Djava.util.logging.config.file=myfile
############################################################
############################################################
# Global properties
############################################################
# "handlers" specifies a comma separated list of log Handler
# classes. These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
handlers= java.util.logging.ConsoleHandler
# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers. For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
.level= INFO
############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################
# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
# Example to customize the SimpleFormatter output format
# to print one-line log message like this:
# <level>: <log message> [<date/time>]
#
# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n
############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################
# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE
2、自定义配置文件
# RootLogger顶级父元素指定默认处理器为:ConsoleHandler
handlers= java.util.logging.ConsoleHandler
# RootLogger 顶级父元素默认的日志级别为:INFO
.level= INFO
# 向日志文件输出的handler 对象
# 指定日志文件路径
java.util.logging.FileHandler.pattern = /logs/test.log
#指定日志文件大小
java.util.logging.FileHandler.limit = 50000
#指定日志文件个数
java.util.logging.FileHandler.count = 1
#指定日志内容的格式
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
# 向控制塔输出的 handler对象
# 指定handler的日志输出级别
java.util.logging.ConsoleHandler.level = INFO
# 指定 handler对象的日志消息格式对象
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
# 指定字符编码
java.util.logging.ConsoleHandler.encoding = UTF-8
# 指定日志消息格式
java.util.logging.SimpleFormatter.format = %4$s: %5$s [%1$tc]%n
@Test
public void loggerProperties() throws IOException {
//读取配置文件,通过类加载器加载
InputStream inputStream = JulTest.class.getClassLoader().getResourceAsStream("logging.properties");
//创建LogManager
LogManager logManager = LogManager.getLogManager();
//通过LogManager设置配置信息
logManager.readConfiguration(inputStream);
//创建日志记录器
Logger logger = Logger.getLogger("com.cmb.jultest");
//测试
logger.severe("测试severe");
logger.warning("测试warning");
logger.info("测试info");
logger.config("测试config");
logger.fine("测试fine");
logger.finer("测试finer");
logger.finest("测试finest");
}
2.2 Log4j学习
2.2.1 Layout日志信息格式
org.apache.log4j.HTMLLayout(以HTML格式布局),
org.apache.log4j.xml.XMLLayout(以XML格式布局),
org.apache.log4j.PatternLayout(可以灵活地自定义布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
2.2.2 appender
Appender用来指定日志输出到那个地方,可以同时指定日志的输出目的地。Log4j常用的输出目的地有以下几种:
输出端类型 | 作用 |
ConsoleAppender | 将日志输出到控制台 |
FileAppender | 将日志输出到文件中 |
DailyRollingFileAppender | 将日志输出到一个日志文件,并且每天输出到一个新文件 |
RollingFileAppender | 将日志信息输出到一个日志文件,并且制定文件的尺寸,当文件大小达到制定尺寸,会自动把文件改名,同时生成一个新的文件 |
JDBCAppender | 把日志信息保存到数据库中 |
以下测试代码为实例:
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
package com.log.log4jtest;
import org.apache.log4j.Logger;
public class Log4jTest {
public static void main(String[] args) {
//开启log4j内部日志记录
// LogLog.setInternalDebugging(true);
Logger logger = Logger.getLogger(Log4jTest.class);
for (int i = 0; i < 5000; i++) {
logger.fatal("fatal");
logger.error("error");
logger.warn("warn");
logger.info("info");
logger.debug("debug");
logger.trace("trace");
}
}
}
2.2.2.1 ConsoleAppender配置
log4j.xml配置如下:
# 指定 RootLogger顶级父元素默认配置信息
# 指定日志级别=trace,使用的 appender为=console
log4j.rootLogger = trace,console
# 指定控制台日志输出的 appender
log4j.appender.console = org.apache.log4j.ConsoleAppender
# 指定消息格式 layout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
log4j.appender.console.layout.conversionPattern = [%p]%r %l %d{yyyy-MM-dd HH:mm:ss} %m%n
日志输出效果如下:
[FATAL]1852 Log4jTest.main(Log4jTest.java:11) 2021-06-26 16:46:59 fatal
[ERROR]1852 Log4jTest.main(Log4jTest.java:12) 2021-06-26 16:46:59 error
[WARN]1852 Log4jTest.main(Log4jTest.java:13) 2021-06-26 16:46:59 warn
[INFO]1852 Log4jTest.main(Log4jTest.java:14) 2021-06-26 16:46:59 info
[DEBUG]1852 Log4jTest.main(Log4jTest.java:15) 2021-06-26 16:46:59 debug
[TRACE]1852 Log4jTest.main(Log4jTest.java:16) 2021-06-26 16:46:59 trace
2.2.2.2 FileAppender配置
log4j.xml配置如下:
# 指定 RootLogger顶级父元素默认配置信息
# 指定日志级别=trace,使用的 appender为=file
log4j.rootLogger = trace,file
# 日志文件输出的 appender 对象
log4j.appender.file = org.apache.log4j.FileAppender
# 指定消息格式 layout
log4j.appender.file.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
log4j.appender.file.layout.conversionPattern = [%p]%r %l %d{yyyy-MM-dd HH:mm:ss} %m%n
# 指定日志文件保存路径
log4j.appender.file.file = /logs/log4j.log
# 指定日志文件的字符集
log4j.appender.file.encoding = UTF-8
日志输出效果:
2.2.2.3 RollingFileAppender配置
log4j.xml配置如下:
log4j.rootLogger = trace,rollingFile
# 按照文件大小拆分的appender对象
log4j.appender.rollingFile = org.apache.log4j.RollingFileAppender
# 指定消息格式 layout
log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
log4j.appender.rollingFile.layout.conversionPattern = [%p]%r %l %d{yyyy-MM-dd HH:mm:ss} %m%n
# 指定日志文件保存路径
log4j.appender.rollingFile.file = /logs/log4j.log
# 指定日志文件的字符集
log4j.appender.rollingFile.encoding = UTF-8
# 指定单个文件大小
log4j.appender.rollingFile.maxFileSize = 1048576
# 指定文件个数
log4j.appender.rollingFile.maxBackupIndex=10
日志输出效果:
2.2.2.4 DailyRollingFileAppender配置
log4j.xml配置如下:
log4j.rootLogger = trace,dailyFile
# 按照时间规则拆分的appender对象
log4j.appender.dailyFile = org.apache.log4j.DailyRollingFileAppender
# 指定消息格式 layout
log4j.appender.dailyFile.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
log4j.appender.dailyFile.layout.conversionPattern = [%p]%r %l %d{yyyy-MM-dd HH:mm:ss} %m%n
# 指定日志文件保存路径
log4j.appender.dailyFile.file = /logs/logs/log4j.log
# 指定日志文件的字符集
log4j.appender.dailyFile.encoding = UTF-8
# 指定文件拆分规则
log4j.appender.dailyFile.datePattern = '.'yyyy-MM-dd-HH-mm-ss
日志输出效果:
2.2.3 Layouts
布局期Layouts用于控制日志输出内容的格式,让我们可以使用各种需要的格式输出日志。Log4j常用的Layouts:
格式化器类型 | 作用 |
HTMLLayout | 格式化日志输出为HTML表格形式 |
SimpleLayout | 简单的日志输出格式化,打印的日志格式为(info - message) |
PatternLayout | 最强大的格式化器,可以根据自定义格式输出日志,如果没有指定转化格式,就用默认的转化格式 |
2.2.4 Layout的格式
log4j采用类似 C语言的printf函数的打印格式格式化日志信息,具体的占位符及其含义如下:
#%m 输出代码中指定的日志信息
#%p 输出优先级,及 DEBUG、INFO 等
#%n 换行符(Windows平台的换行符为 "\n",Unix 平台为 "\n")
#%r 输出自应用启动到输出该 log 信息耗费的毫秒数
#%c 输出打印语句所属的类的全名
#%t 输出产生该日志的线程全名
#%d 输出服务器当前时间,默认为 ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日 HH:mm:ss}
#%l 输出日志时间发生的位置,包括类名、线程、及在代码中的行数。如:
#Test.main(Test.java:10)
#%F 输出日志消息产生时所在的文件名称
#%L 输出代码中的行号
#%% 输出一个 "%" 字符
可以在 % 与字符之间加上修饰符来控制最小宽度、最大宽度和文本的对其方式。如:
%5c 输出category名称,最小宽度是5,category<5,默认的情况下右对齐
%-5c 输出category名称,最小宽度是5,category<5,"-"号指定左对齐,会有空格
%.5c 输出category名称,最大宽度是5,category>5,就会将左边多出的字符截掉,<5不
会有空格
%20.30c category名称<20补空格,并且右对齐,>30字符,就从左边交远销出的字符截掉
2.2.5 自定义logger
log4j.rootLogger = trace,console
# 自定义Logger 对象设置
# 自定义日志级别: com.log.log4jtest下的日志采用info级别,使用file
log4j.logger.com.log.log4jtest = info,file
日志输出效果:
com.log.log4jtest包下的日志级别都是info以上
2.3 JCL学习(淘汰)
全称为Jakarta Commons Logging,是Apache提供的一个通用日志API。
它是为“所有java日志实现”提供一个统一的接口,它自身也提供了一个日志实现,但是功能非常弱(SimpleLog)。所以一般不会单独使用它。它允许你开发人员使用不同的具体日志实现工具:Log4j,Jdk自带的日志JUL
JCL有两个基本抽象类:Log(基本记录器)和LogFactory(负责创建Log实例)
2.4 Slf4j 学习
slf4j调用逻辑图
slf4j是日志门面,依赖具体的日志实现。
slf4j只能同时导入一个日志实现,导入多个日志实现会报错。
依赖:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>
2.4.1 slf4j + log4j
log4j 和 slf4j 结合使用,需要使用适配器
依赖:
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.32</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
log4j.properties配置:
log4j.rootLogger=INFO,console
log4j.additivity.org.apache=true
#console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=INFO
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
测试代码:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Slf4jLog4j {
private final static Logger logger = LoggerFactory.getLogger(Slf4jLog4j.class);
public static void main(String[] args) {
logger.error("测试");
logger.info("info级别");
}
}
测试结果:
2021-09-25 23:20:38 [ERROR] 测试
2021-09-25 23:20:38 [INFO] info级别
2.5 logback学习
logback比log4j性能高
学习产出: