很早就想过能不能将一些日志信息保存到数据库中去,譬如在应用程序中增删改了一些信息,而这样到信息很敏感的,需要记录在案,甚至是操作人、操作时间等,还有就是可能有的人想看看自己的相关的内容是否被查看修改过,等等。怎么样才能达到这样的需求呢,我想log是一种解决方法。但通常的log大多是保存在文件系统中,这样的数据虽然也是很有规律的,但总结起来却并不简单,而关系型数据库却能很好的达到这样的效果,因此可以将log格式化数据保存到数据库中。
好在log4j已经有了这样的功能,那就是JDBCAppender,只需要配置好这个appender就可以完成上面的要求了。
下面来看代码吧:
log4j.properties
log4j.rootLogger=info,db
log4j.appender.db=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.db.driver=com.mysql.jdbc.Driver
log4j.appender.db.URL=jdbc:mysql://127.0.0.1/log
log4j.appender.db.bufferSize=10
log4j.appender.db.user=root
log4j.appender.db.password=123
log4j.appender.db.sql=insert into log (LogName,UserName,Class,Method,createTime,LogLevel,MSG) values ('%X{userId}','%X{userName}','%C','%M','%d{yyyy-MM-dd HH:mm:ss}','%p','%m')
log4j.appender.db.layout=org.apache.log4j.PatternLayout
Test.java
public class Test {
public static void main(String[] args) {
PropertyConfigurator
.configure("D:\\workspace\\cadillac\\search\\src\\main\\java\\log4j.properties");
MDC.put("userId", "lk");
MDC.put("userName", "lk");
Logger log = Logger.getLogger(Test.class);
for (int i = 0; i < 11; i++) {
log.info("this is a test");
}
}
}
代码就这么多,run一下就可以了
但是在main中会看到有一个for循环。其原因是这样的:
在配置文件中有:log4j.appender.db.bufferSize=10配置项
从名称可以看出这是设置bufferSize的,而这个有什么用呢?bufferSize的作用就不要说了,看字面的意思也知道的。问
题是如果上面没有循环,那么log.info()只会运行一次,这样buffer.size()也就是1了(可以理解为log.info()一次就会向
buffer中写入一次),这时是不会执行数据库插入操作的。这是因为在JDBCAppender的append方法中有这样的逻辑:
public void append(LoggingEvent event) {
buffer.add(event);
if (buffer.size() >= bufferSize)
flushBuffer();
}
只有当buffer.size() 大于bufferSize时才会执行flushBuffer()操作的,而数据库的插入操作就是被这个方法引用的,
所以如果main方法中不循环,则很有可能不会看到数据库有新增的数据了。
还有一点:在JDBCAppender注释中提到JDBCAppender是将会被淘汰的,其意思是最好自己实现一个类似的
Appender,个人觉得可能是JDBCAppender的数据库连接和sql操作上会有问题吧,致使文档中这样一段注释。