目录
1. 前言
2. 日志门面
3. 日志库
4. 日志适配器
5. 日志库的选用
6.logback.xml 配置文件
1. 前言
说到日志工具, 日常工作或学习中肯定听过这些名词: log4j,logback,jdk-logging,slf4j,commons-logging 等, 它们之间有什么关系, 在整个日志体系中又扮演什么角色呢?
日志框架分为三大类, 包括日志门面, 日志适配器, 日志库. 利用门面设计模式, 即 Facade 来进行解耦, 使日志使用变得更简单.
2. 日志门面
门面设计模式是面向对象设计模式中的一种, 日志框架采用的就是这种模式, 类似 JDBC 的设计理念. 它只提供一套接口规范, 自身不负责日志功能的实现, 目的是让使用者不需要关注底层具体是哪个日志库来负责日志打印机具体的使用细节等. 目前用得最为广泛的日志门面有两种: slf4j 和 commons-logging
3. 日志库
它巨头实现了日志的相关功能, 主流的日志库有三个, 分别是 log4j,log-jdk,logback. 最早 Java 想要记录日志只能通过 System.out 或 System.err 来完成, 非常不方便. log4j 就是为了解决这一问题而提出的, 它是最早诞生的日志库. 接着 JDK 也在 1.4 版本引入了一个日志库 java.util.logging.Logger, 简称 log-jdk. 这样市面上就出现了两种日志功能的实现, 开发者在使用时需要关注所使用的日志库的具体细节. logback 是最晚出现的, 它与 log4j 出自同一个作者, 是 log4j 的升级版且本身就实现了 slf4j 的接口.
4. 日志适配器
日志适配器分为两种场景:
日志门面适配器, 因为 slf4j 规范是后来提出的, 在此之前的日志库是没有实现 slf4j 的接口的, 例如 log4j. 所以, 在工程里要想使用 slf4j+log4j 的模式, 就额外需要一个适配器 (slf4j+log4j12) 来解决接口不兼容的问
日志库适配器, 在一些老的工程里, 一开始为了开发简单而直接使用了日志库 API 来完成日志打印, 随着时间的推移想将原来直接调用日志库的模式改为业界标准的门面模式(例如 slf4j+logback 组合), 但老工程代码里打印日志的地方太多, 难以改动, 所以需要一个适配器来完成从旧日志库的 API 到 slf4j 的路由, 这样在不改动原有代码的情况下也能使用 slf4j 来统一管理日志, 而且后续自由替换具体日志库也不是问题.
5. 日志库的选用
如果是新工程, 则推荐使用 slf4j+logback 模式, 因为 logback 自身实现了 slf4j 的接口, 不需要额外引入适配器, 另外 logback 是 log4j 的升级版, 具备比 log4j 更多的优点, 可通过如下配置进行集成:
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-API</artifactId>
- <version>${slf4j-API.version}</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-core</artifactId>
- <version>${logback-core.version}</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- <version>${logback-classic.version}</version>
- </dependency>
如果是老工程, 则需要根据所使用的日志库来确定门面适配器, 通常情况下老工程使用的都是 log4j, 因此以 log4j 日志库为例, 可通过如下配置进行集成:
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-API</artifactId>
- <version>${slf4j-API.version}</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- <version>${slf4j-log4j12.version}</version>
- </dependency>
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- <version>${log4j.version}</version>
- </dependency>
如果老代码直接使用了 log4j 日志库提供的接口来打印日志, 则还需要引入日志库适配器, 配置实例如下所示:
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>log4j-over-slf4j</artifactId>
- <version>${log4j-over-slf4j.version}</version>
- </dependency>
6.logback.xml 配置文件
- <?xml version="1.0" encoding="UTF-8"?>
- <configuration scan="true">
- <property name="application_name" value="web" />
- <property name="LOG_PATH" value="c:" />
- <!-- 控制台输出 -->
- <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
- <encoder charset="UTF-8">
- <pattern>%date %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern>
- <!-- <pattern>%date [%thread] %-5level %logger{80} - %msg%n</pattern> -->
- </encoder>
- </appender>
- <!-- 时间滚动输出 文件日志 -->
- <appender name="file-debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
- <level>debug</level>
- </filter>
- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <FileNamePattern>${LOG_PATH}/logs/${application_name}/${application_name}_debug.%d{yyyy-MM-dd}_%i.log</FileNamePattern>
- <MaxHistory>100</MaxHistory>
- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
- <maxFileSize>10mb</maxFileSize>
- </timeBasedFileNamingAndTriggeringPolicy>
- </rollingPolicy>
- <encoder charset="UTF-8">
- <pattern>%date [%thread] %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern>
- </encoder>
- </appender>
- <!-- 时间滚动输出 文件日志 -->
- <appender name="file-info" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
- <level>info</level>
- </filter>
- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <FileNamePattern>${LOG_PATH}/logs/${application_name}/${application_name}_info.%d{yyyy-MM-dd}_%i.log</FileNamePattern>
- <MaxHistory>100</MaxHistory>
- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
- <maxFileSize>10mb</maxFileSize>
- </timeBasedFileNamingAndTriggeringPolicy>
- </rollingPolicy>
- <encoder charset="UTF-8">
- <pattern>%date [%thread] %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern>
- </encoder>
- </appender>
- <!-- 时间滚动输出 level 为 ERROR 日志 -->
- <appender name="file-error" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <filter class="ch.qos.logback.classic.filter.LevelFilter">
- <level>ERROR</level>
- <onMatch>ACCEPT</onMatch>
- <onMismatch>DENY</onMismatch>
- </filter>
- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <FileNamePattern>${LOG_PATH}/logs/${application_name}/${application_name}_error.%d{yyyy-MM-dd}_%i.log</FileNamePattern>
- <MaxHistory>100</MaxHistory>
- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
- <maxFileSize>10mb</maxFileSize>
- </timeBasedFileNamingAndTriggeringPolicy>
- </rollingPolicy>
- <encoder charset="UTF-8">
- <pattern>%date [%thread] %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern>
- </encoder>
- </appender>
- <Logger name="org.apache.http.impl.conn.PoolingHttpClientConnectionManager" level="DEBUG" additivity="false">
- <appender-ref ref="file-debug" />
- </Logger>
- <appender name="ASYNC-ERROR" class="ch.qos.logback.classic.AsyncAppender">
- <!-- 不丢失日志. 默认的, 如果队列的 80% 已满, 则会丢弃 TRACT,DEBUG,INFO 级别的日志 -->
- <discardingThreshold>0</discardingThreshold>
- <!-- 更改默认的队列的深度, 该值会影响性能. 默认值为 256 -->
- <queueSize>256</queueSize>
- <!-- 添加附加的 appender, 最多只能添加一个 -->
- <appender-ref ref="file-error"/>
- </appender>
- <root level="info">
- <appender-ref ref="stdout" />
- <appender-ref ref="file-info" />
- <appender-ref ref="file-error" />
- </root>
- </configuration>
实例代码如下:
private static final Logger logger =LoggerFactory.getLogger(ConfigureQuartz.class);
注意, logger 对象被定义为 static 变量, 这是因为这个 logger 与当前类绑定, 避免每次都 new 一个新对象, 造成资源浪费, 甚至引发 OutOfMemoryError 问题.
在使用 slf4j + 具体日志库模式时, 由于 slf4j 相当于充当 API 抽象接口, 所以我们的日志打印是也是面向接口编程的, 当我们需要更换具体的日志库时, 我们只需要引入具体的 maven 依赖就可以了, 并对原有的日志库依赖进行移除, 而不需要改动代码. 至此, slf4j 的架构原理讲解完成, 之后会对具体的日志库 logback 的配置文件进行讲解, 本章只是先简单给出 logback.xml 配置文件的基本模板, 下一章节《日志系列 2--logback 配置文件详解》敬请期待.
来源: https://www.cnblogs.com/bmbi/p/12884981.html