文章目录
1. Mybatis日志
1.1 日志实现原理
-
Mybatis 通过使用内置的日志工厂提供日志功能。 内置日志工厂将会把日志工作委托给下面的实现之一:
- SLF4J
- Apache Commons Logging
- Log4j2
- Log4j
- JDK logging
-
MyBatis 内置日志工厂会基于运行时检测信息选择日志委托实现。它会(按上面罗列的顺序)使用第一个查找到的实现。当没有找到这些实现时,将会禁用日志功能。
1.2 日志实现方式
-
不少应用服务器(如 Tomcat 和 WebShpere)的类路径中已经包含 Commons Logging。注意,在这种配置环境下,MyBatis 会把 Commons Logging 作为日志工具。这就意味着在诸如 WebSphere 的环境中,由于提供了 Commons Logging 的私有实现,你的 Log4J 配置将被忽略。这个时候你就会感觉很郁闷:看起来 MyBatis 将你的 Log4J 配置忽略掉了(其实是因为在这种配置环境下,MyBatis 使用了 Commons Logging 作为日志实现)。
-
如果你的应用部署在一个类路径已经包含 Commons Logging 的环境中,而你又想使用其它日志实现,你可以通过在 MyBatis 配置文件 mybatis-config.xml 里面添加一项 setting 来选择其它日志实现。
-
setting配置日志的有效取值
- 可选的值有: SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING,或者是实现了 org.apache.ibatis.logging.Log 接口,且构造方法以字符串为参数的类完全限定名。
- 示例:
- 仅当运行时类路径中存在该日志实现时,日志实现的切换才会生效。 如果你的环境中并不存在 Log4J,你却试图调用了相应的方法,MyBatis 就会忽略这一切换请求,并将以默认的查找顺序决定使用的日志实现。
- 可选的值有: SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING,或者是实现了 org.apache.ibatis.logging.Log 接口,且构造方法以字符串为参数的类完全限定名。
2. SLF4J
- SLF4J其实只是一个门面服务而已,他并不是真正的日志框架,真正的日志的输出相关的实现还是要依赖Log4j、logback等日志框架的。
- 简单日志门面(simple logging Facade for java),slf4j并不是一个完整的日志框架,他只是为各种日志框架提供统一的API接口,及根据slf4j提供的接口规则使用Logger,而在部署的时候根据自己的需求配置自己希望使用的日志系统。可以说他是将各个日志系统接口进行了抽象,抽象为统一的slf4j接口,这样只要项目中使用slf4j API,我们可以随时更换日志实现,而不用更改代码。
2.1 slf4j日志级别
SLF4J将日志分为trace、debug、info、warn、error五个级别,每个级别对应记录不同的日志,对应不同的使用场景。
- trace: trace是最低优先级的日志,一般用来追踪详细的程序运行流,比如程序的运行过程中,运行到了哪一个方法,进入了哪一条分支。通过trace程序的运行流程,可以判断程序是否按照期望的逻辑在运行。
- debug: debug是比trace高一级别的日志,该级别的日志就是用来debug用的。这类日志往往用在判断是否有出现bug的场景,且往往记录了代码运行的详细信息,比如方法调用传入的参数信息。
- info: info比debug高一级别,用来记录程序运行的一些关键信息,比如系统运行到了哪一个阶段,到达了哪一个状态。
- warn: warn比info的级别更高,用来记录一些警告信息。警告信息表示,程序进入了一个特殊的状态,在该状态下程序可以继续运行,但是不建议让程序进入该状态,因为该状态可能导致结果出现问题。
- error: error级别的日志是最高优先级了,用来记录运行时的错误信息,表示程序运行过程中出现了需要被解决的问题,往往是一些异常。使用error日志的时候,一般会将详细的异常出现的原因记录
2.2 日志门面与日志实现
(1)日志门面
- 日志门面为日志系统也提供一套接口规范,日志系统通过这套日志门面进行开发避免了直接依赖具体的日志框架。
(2)日志实面
- 具体日志功能的实现框架
(3)关系
- 日志系统一般分为,日志门面和日志实面(实现);在使用了日志门面后,更改日志框架的时候就不需要修改底层代码;
- 日志门面与日志实现是接口与实现类的关系;
- 日志门面可以理解为java中的一个interface(接口),而日志实面就是就是实现类。
- 日志实面即为日志实现,实现了日志门面中所规定的日志系统所需实现的功能,也就是说日志实面是日志门面中接口的实现类。
(4)优点
- 面向接口开发,不再依赖具体的实现类。减少代码的耦合。
- 项目通过导入不同的日志实现类,可以灵活的切换日志框架
- 统一API,方便开发者学习和使用
- 统一配置便于项目日志的管理
2.3 日志门面与日志依赖配置
- mybatis日志设置
<settings>
<setting name="logImpl" value="SLF4J"/>
</settings>
(1)slf4j + log4j
<!-- slf4j日志门面 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- 引入slf4j对应log4j的桥接器 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<!-- log4j日志实面(日志实现框架) -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
(2)slf4j + log4j2
<!-- slf4j日志门面 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- 引入slf4j对应log4j2的桥接器 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<scope>runtime</scope>
<version>2.11.0</version>
</dependency>
<!-- log4j2日志实面(日志实现框架) -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<scope>runtime</scope>
<version>2.11.0</version>
</dependency>
3. LOG4J
Log4j 是 Apache 的一个开放源代码项目,通过使用 Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI 组件、甚至是套接口服务 器、NT 的事件记录器、UNIX Syslog 守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就 是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
3.1 日志级别
每个Logger都被了一个日志级别(log level),用来控制日志信息的输出。
日志级别从高到低分为:
- fatal 指出每个严重的错误事件将会导致应用程序的退出。
- error 指出虽然发生错误事件,但仍然不影响系统的继续运行。
- warn 表明会出现潜在的错误情形。
- info 一般和在粗粒度级别上,强调应用程序的运行全程。
- debug 一般用于细粒度级别上,对调试应用程序非常有帮助。
- trace 是程序追踪,可以用于输出程序运行中的变量,显示执行的流程。
- 还有两个特殊的级别:
- OFF,可用来关闭日志记录。
- ALL,启用所有消息的日志记录。
3.2 log4j重要组件
- log4j从功能实现来说,主要由三大组件组成:Logger、Appender、Layout。(对应关系如下:)
- Logger是日志记录器(也可以说是日志级别)
- Appender是日志输出目的地
- Layout是日志输出格式控制器
- 一个日志记录器可以对应多个输出目的地,每个输出目的地有特定的输出格式。
(1)Logger
- 日志记录器,指定输出日志的级别,并且可以配置输出日志的指定空间
- log4j.prpperties配置
# 自定义logger(指定要输出日志的全限定路径、日志级别、选择的appender)
log4j.logger.com.qf.dao=debug,CONSOLE
- log4j.xml配置
<!-- 自定义logger,additivity 日志是否在父Logger中输出(即root中))-->
<!-- 自定义logger(指定要输出日志的全限定路径、日志级别、选择的appender)-->
<logger name="com.qfedu.dao" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="LOGFILE"/>
</logger>
(2)Appender
- log4j将日志输出源称为Appender,每个输出源一个Appender,一个logger可以对应多个Appender。
- 常见Appender
- org.apache.log4j.ConsoleAppender:控制台输出
- org.apache.log4j.FileAppender:输出到文件
- org.apache.log4j.DailyRollingFileAppender:每天产生日志输出到文件
- org.apache.log4j.RollingFileAppender:文件达到指定大小产生新文件
- org.apache.log4j.WriterAppender:以流格式发送到指定位置
- org.apache.log4j.jdbc.JDBCAppender:输出到数据库
- log4j.prpperties配置
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c:%L] [%p] - %m%n
- log4j.xml配置
<!-- 日志控制台输出配置-->
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c:%L] [%p] - %m%n"/>
</layout>
</appender>
(3)Layout
- 每个Appender可以指定特定的输出格式,log4j将输出格式称为Layout。
- 常见Layout
- org.apache.log4j.HTMLLayout:HTML格式Layout
- org.apache.log4j.PatternLayout:自定义格式Layout(常用)
- org.apache.log4j.SimpleLayout:包含日志信息级别及信息
- org.apache.log4j.TTCCLayout:包含生产时间、类别、级别等
- 常用PatternLayout
- %m 输出代码中指定的消息
- %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
- %r 输出自应用启动到输出该log信息耗费的毫秒数
- %c 输出所属的类目,通常就是所在类的全名
- %t 输出产生该日志事件的线程名
- %n 输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”
- %-x 左对其信息
3.3 mybatis日志配置log4j
- mybatis配置log4j有以下两种配置方式,主要区别为是否使用日志门面
(1)(日志门面+日志实面):slf4j + log4j
- 步骤1:mybatis日志设置
<settings>
<setting name="logImpl" value="SLF4J"/>
</settings>
- 步骤2:导入相关依赖
<!-- slf4j日志门面 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- 引入slf4j对应log4j的桥接器 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<!-- log4j日志实面(日志实现框架) -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
- 步骤3:编写配置文件
-
log4j基于自动配置,所以配置文件名称只能为:
log4j.properties
或log4j.xml
-
以下示例仅展示文件输出与控制台输出配置
-
配置1:log4j.properties
# Set root category priority to INFO and its only appender to CONSOLE.
log4j.rootLogger=debug, CONSOLE, LOGFILE
# 表示自定义的logger不会继承父Logger的appender输出,默认为true及输出
lo4j.log4j.additivity.org.apache=false
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c:%L] [%p] - %m%n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\mybatis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c:%L] [%p] - %m%n
# 自定义logger(指定要输出日志的全限定路径、日志级别、选择的appender)
log4j.logger.com.qf.dao=debug,CONSOLE
配置2:log4j.xml
- 自定义logger(指定要输出日志的全限定路径、日志级别、选择的appender),可以选择多个appender
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration debug="true">
<!-- 日志控制台输出配置-->
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c:%L] [%p] - %m%n"/>
</layout>
</appender>
<!-- 日志文件输出配置-->
<appender name="LOGFILE" class="org.apache.log4j.FileAppender">
<param name="File" value="d:\mybatis.log"/>
<param name="Append" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c:%L] [%p] - %m%n"/>
</layout>
</appender>
<!-- 自定义logger,additivity 日志是否在父Logger中输出(即root中))-->
<!-- 自定义logger(指定要输出日志的全限定路径、日志级别、选择的appender)-->
<logger name="com.qfedu.dao" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="LOGFILE"/>
</logger>
<!-- 根logger-->
<root>
<level value="debug "/>
<appender-ref ref="CONSOLE"/>
</root>
</log4j:configuration>
(2)(不使用日志门面–不推荐): log4j
- 步骤1:mybatis日志设置
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
- 步骤2:导入相关依赖
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
- 步骤3:编写配置文件
- log4j基于自动配置,所以配置文件名称只能为:
log4j.properties
或log4j.xml
- 以下示例仅展示文件输出与控制台输出配置
- 参考上述方式一示例
- log4j基于自动配置,所以配置文件名称只能为:
3. LOG4J2
Apache Log4j2 是对Log4j 的升级:(Log4j2已经不仅仅是Log4j的一个升级版本了,而是从头到尾被重写的,这可以认为这其实就是完全不同的两个框架。)
- 异常处理,在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异常处理机制。
- 性能提升,log4j2 相较于log4j 和 logback 都具有明显的性能提升,有18倍性能提升。
- 自动重载配置,参考了logback的设计,当然会提供自动刷新参数配置,最实用的就是我们在生产上可以动态的修改日志的级别而不需要重启应用。
- 无垃圾机制,log4j2 在大部分情况下,都可以使用其设计的一套无垃圾机制【对象重用、内存缓冲】,避免频繁的日志收集导致的 jvm gc。
3.1 mybatis配置log4j2
- mybatis配置log4j2有以下两种配置方式,主要区别为使用哪一个日志门面,一般情况下,由于log4j功能过于强大,所以
slf4j + log4j2
会是后续流行的搭配!
(1)log4j2(日志+门面) - 步骤1:配置mybatis文件
<settings>
<setting name="logImpl" value="LOG4J2"/>
</settings>
- 步骤2:导入相关依赖
<!-- log4j2日志门面-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.11.2</version>
</dependency>
<!-- log4j2日志实面(日志实现)-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.2</version>
</dependency>
- 步骤3:编写log4j2配置文件
—— 见下文
(2)slf4j + log4j2
- 步骤1:配置mybatis文件
<settings>
<setting name="logImpl" value="SLF4J"/>
</settings>
- 步骤2:导入相关依赖
<!-- slf4j日志门面 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- 引入slf4j对应log4j2的桥接器 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<scope>runtime</scope>
<version>2.11.0</version>
</dependency>
<!-- log4j2日志实面(日志实现框架) -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<scope>runtime</scope>
<version>2.11.0</version>
</dependency>
- 步骤3:编写log4j2配置文件
—— 见下文
3.2 log4j2配置文件
(1)配置文件格式
- 注意配置文件命名格式
(2)配置文件内容(只展示控制台输出和文件输出)
- log4j2从和log4j的组件含义大致相同,只是Appender组件子组件名称不同,功能实现来说,主要由三大组件组成:Logger、Appender、Layout。(对应关系如下:)
- Logger是日志记录器(也可以说是日志级别)
- Appender是日志输出目的地
- Layout是日志输出格式控制器
- 一个日志记录器可以对应多个输出目的地,每个输出目的地有特定的输出格式。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<!-- 日志输出到控制台-->
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout pattern="[%t] %-5level %logger{36} - %msg%n"/>
</Console>
<!-- 日志输出到文件-->
<File name="LOGFILE" fileName="d:\mybatis.log" append="true">
<PatternLayout pattern="[%t] %-5level %logger{36} - %msg%n"/>
</File>
</Appenders>
<Loggers>
<!-- 自定义日志记录器-->
<Logger name="com.j2205.wangwenfei.mapper" level="trace" additivity="false">
<AppenderRef ref="CONSOLE"/>
<AppenderRef ref="LOGFILE"/>
</Logger>
<!-- 根日志记录器-->
<Root level="error" >
<AppenderRef ref="CONSOLE"/>
</Root>
</Loggers>
</Configuration>
(3)log4j2 配置文件含义
-
Loggers 指定logger,logger与appeder进行关联,将logger中的日志输出到appender,由appender实现日志的控制台输出或者文件记录。
- Root 用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出
- level 日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
- AppenderRef用来指定该日志输出到哪个Appender.(可以配置多项)。
-
Logger 自定义的子日志
- level 日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF。
- name 用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点。
- additivity 日志是否在父Logger中输出。
- AppenderRef用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root.
如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出
,此时我们可以设置Logger的additivity="false"只在自定义的Appender中进行输出。