利用 log4j 打印 mybaits
一、前言
为了便于学习和程序调试,想利用 log4j 帮忙打印我用 mybatis 执行的 sql 语句,当前的状态是,我的项目里没有一点关于 log4j 的东西,以此为起点,到 log4j 能够答应出我想要的 sql 为止是本篇的内容,而 log4j 更深入的学习,留到以后再说。
二 用 log4j 打印出 Hello World
从官网下载 log4j 的 jar 包,jar 包有很多,我们先导入 log4j-api-{版本号}.jar 和 log4j-core-{版本号}.jar 这两个 jar 包,然后,我们就可以开始使用 log4j 了。看下面这段代码:
1 import org.apache.logging.log4j.LogManager; 2 import org.apache.logging.log4j.Logger; 3 4 public class Log4jTest { 5 6 private static final Logger logger = LogManager.getLogger("HelloWorld"); 7 public static void main(String[] args) { 8 logger.error("Hello, World!"); 9 } 10 11 } 12 /*output: 13 ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), 14 or user programmatically provided configurations. 15 Set system property 'log4j2.debug' to show Log4j 2 internal initialization 16 logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2 17 11:07:59.153 [main] ERROR HelloWorld - Hello, World!*/
这也是官网给出的示例代码,从输出可以看到 "Hello,World",表明我们这个程序时成功的。
关于 LoggerManager.getLogger 这是 log4j2 生产 Logger 的最普遍和最推荐的方式,我们只需要知道当我们需要一个 Logger 去打印日志时,使用这个方法即可。从输出我们可以看到,默认配置下打印的信息是 时间 + 线程 + 输出类型 + 我们生产 Logger 是传入的 String 参数 + Message。这是 log4j 输出的标准格式。
三、log4j 的配置
上面的代码虽然成功了,但是有瑕疵,就是输出最上面的 EROOR,这个错误的意思是,log4j 没能找到配置文件,所以使用的是默认配置(只有 errors 会打印到控制台)。
那么什么是 log4j 的配置,它又是如何去使用这个配置文件的?
首先,我们先不讨论框架下的 log4j 如何启动等等,在我们刚才的示例程序中,当我们通过 LoggerManager.getLogger(String args) 去获取一个 Logger 时,log4j 会自动去寻找它的配置文件。
通过 log4j 官网 https://logging.apache.org/log4j/2.x/manual/configuration.html 我们获取到的信息是,log4j 会根据 log4j.configurationFile 这个系统属性去查找对应的配置文件,而如果没有这个系统属性话,我自动去 classpath 下查找配置文件,log4j.configurationFile 我们先不管,而是采用让 log4j 自己去 classpath(对于本程序就是src 目录下)寻找,而它的配置文件是有几种格式的,我们不一一列出,只要会使用一种即可,我们选择的是 log4j2.properties 需要注意,这里的名称一定要正确无误。
现在,我们就在 src 下创建一个 log4j2.properties 文件,里面的内容,先用 官网提供的模板:
status = error dest = err name = PropertiesConfig property.filename = target/rolling/rollingtest.log filter.threshold.type = ThresholdFilter filter.threshold.level = debug appender.console.type = Console appender.console.name = STDOUT appender.console.layout.type = PatternLayout appender.console.layout.pattern = %m%n appender.console.filter.threshold.type = ThresholdFilter appender.console.filter.threshold.level = error appender.rolling.type = RollingFile appender.rolling.name = RollingFile appender.rolling.fileName = ${filename} appender.rolling.filePattern = target/rolling2/test1-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz appender.rolling.layout.type = PatternLayout appender.rolling.layout.pattern = %d %p %C{1.} [%t] %m%n appender.rolling.policies.type = Policies appender.rolling.policies.time.type = TimeBasedTriggeringPolicy appender.rolling.policies.time.interval = 2 appender.rolling.policies.time.modulate = true appender.rolling.policies.size.type = SizeBasedTriggeringPolicy appender.rolling.policies.size.size=100MB appender.rolling.strategy.type = DefaultRolloverStrategy appender.rolling.strategy.max = 5 logger.rolling.name = com.example.my.app logger.rolling.level = debug logger.rolling.additivity = false logger.rolling.appenderRef.rolling.ref = RollingFile rootLogger.level = info rootLogger.appenderRef.stdout.ref = STDOUT
关于配置文件,我们先使用官网给的模板,然后需要修改什么属性,然后再对该属性进行说明。
然后,我们再运行之前的程序,输出结果中的 Error 就消失了。但是仅仅输出了一个 Hello World,至于时间,类型,都不见了,这肯定是因为配置文件的原因。我们重点看下面这些配置:
appender.console.layout.type = PatternLayout appender.console.layout.pattern = %m%n
在这分配置文件里,我们把 log4j 的布局样式设置成了,PatternLayout,而我们也只需要去注意 PatternLayout 就行了,其他类型暂不讨论。
上配置第一行,指定了我们的输出的样式类型是 PatternLayout
第二行则设置了 Pattern(模板)也就是输出那些信息,和信息的格式,目前的设置 %m%n 表示输出 message 和一个换行符。
关于 pattern 的详细信息,可以看官网的解释:https://logging.apache.org/log4j/2.x/manual/layouts.html
如果我们需要恢复到“时间 + 线程 + 输出类型 + 我们生产 Logger 是传入的 String 参数(也就是 logger 的名称) + Message” 的格式,需要怎么设置 pattern?
首先,我们需要找到代表时间、线程...的字符,并且用 %+字符的形式代表。比如 %m 表示 message
时间:d,同时在d 后面可以跟一些属性表示时间的输出格式,官网有对应的表格,我们这里选用默认即可,也就是用 %d 表示时间。
线程:t,代指 Thread
输出类型: p,代指 print
log name:c。
综上,我们将 pattern 设置成 [%p] %d: [Thread-%t : %c] %m%n (加上了一些赋值的字符便于阅读)。
允许程序,输出结果为:
[ERROR] 2018-10-01 15:59:52,172: [Thread-main : HelloWorld] Hello, World!
四、使用 log4j 打印 mybatis 的 sql 信息
这一步很简单,我们只需要在 mybatis-config.xml 里加入下面的 setting 即可:
<!-- settting --> <settings> <setting name="logImpl" value="LOG4J2" /> </settings>
这时候,我们运行一个使用 mybatis 的程序,会发现,还是没有输出任何 sql 信息。这是因为,我们目前的 log4j 配置的输出级别还不够,要想打印 sql 输出级别至少是 debug 才行,
输出级别首先受到 appender.console.filter.threshold.level 的限制,目前是 error 我们改成 debug,其实,还受到 rootLogger (应该是所有 logger 的父类),所以我们将倒数第二行的 rootLogger.level 也设置成 debug,即可输出 sql。
在我原来的 mybatis 测试的项目的基础上,我做了 3 件事完成了利用 log4j 输出 sql 的功能:
- 引入了 log4j 的 jar 包;
- 配置了 log4j2.properties;
- 在 mybatis-config.xml 添加了 log4j 作为输出。
log4j2.properties:
status = error dest = err name = PropertiesConfig property.filename = target/rolling/rollingtest.log filter.threshold.type = ThresholdFilter filter.threshold.level = debug appender.console.type = Console appender.console.name = STDOUT appender.console.layout.type = PatternLayout appender.console.layout.pattern = [%p] %d: [Thread-%t : %c] %m%n appender.console.filter.threshold.type = ThresholdFilter appender.console.filter.threshold.level = debug appender.rolling.type = RollingFile appender.rolling.name = RollingFile appender.rolling.fileName = ${filename} appender.rolling.filePattern = target/rolling2/test1-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz appender.rolling.layout.type = PatternLayout appender.rolling.layout.pattern = %d %p %C{1.} [%t] %m%n appender.rolling.policies.type = Policies appender.rolling.policies.time.type = TimeBasedTriggeringPolicy appender.rolling.policies.time.interval = 2 appender.rolling.policies.time.modulate = true appender.rolling.policies.size.type = SizeBasedTriggeringPolicy appender.rolling.policies.size.size=100MB appender.rolling.strategy.type = DefaultRolloverStrategy appender.rolling.strategy.max = 5 logger.rolling.name = com.example.my.app logger.rolling.level = debug logger.rolling.additivity = false logger.rolling.appenderRef.rolling.ref = RollingFile rootLogger.level = debug rootLogger.appenderRef.stdout.ref = STDOUT
mybatis-config.xml:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 <!-- 配置别名 --> 7 <!-- 配置 properties --> 8 <properties resource="jdbc.properties"/> 9 <!-- settting --> 10 <settings> 11 <setting name="logImpl" value="LOG4J2" /> 12 </settings> 13 <typeAliases> 14 <package name = "mybatisTest.model"/> 15 </typeAliases> 16 <!-- environment 描述的数据库 --> 17 <environments default="development"> 18 <environment id="development"> 19 <!-- 表示事务管理器采用的事 mybatis 的 jdbc 管理器方式 --> 20 <transactionManager type="JDBC"/> 21 <dataSource type="POOLED"> 22 <property name="driver" value="${database.driver}"/> 23 <property name="url" value="${database.url}"/> 24 <property name="username" value="${database.username}"/> 25 <property name="password" value="${database.password}"/> 26 </dataSource> 27 </environment> 28 </environments> 29 <mappers> 30 <mapper resource="employee/mapper/EmployeeMapper.xml"/> 31 <mapper resource="salary/mapper/SalaryMapper.xml"/> 32 </mappers> 33 34 </configuration>