之所以想要写这一篇分享是因为前一段时间看了另一个分享,使用日志打印出完整的sql语句,而不是像jfinal内置的devMode中带”?”的sql语句.Jfinal中使用日志框架输出完整sql语句信息
但是遇到了一个问题,该分享中使用的日志框架是logback,但是我的项目中使用的是jfinal自带的日志框架(即配置了log4j.properties),会打印出来很多无用的日志,当时并不知道怎么配置”日志过滤”,就放弃了该分享中的功能,现在终于解决了这个问题,现分享如下:
分享从几个问题开始:
jfinal使用的是封装了一层的日志框架,可以兼容其余所有日志框架,为何这么说,看源码,jfinal源码中有一个接口ILogFactory
,一个抽象类Log
,jfinal源代码中使用的日志工具就是Log的子类.为什么说jfinal可以兼容其余所有日志框架呢?看下jfinal提供的Log实现类,有两个,一个JdkLog,一个Log4jLog,从名字就可以看出,一个是封装Jdk默认log,一个是封装log4j的log,部分代码如下:
public class Log4jLog extends Log {
private org.apache.log4j.Logger log;
private static final String callerFQCN = Log4jLog.class.getName();
Log4jLog(Class<?> clazz) {
log = org.apache.log4j.Logger.getLogger(clazz);
}
Log4jLog(String name) {
log = org.apache.log4j.Logger.getLogger(name);
}
public static Log4jLog getLog(Class<?> clazz) {
return new Log4jLog(clazz);
}
public static Log4jLog getLog(String name) {
return new Log4jLog(name);
}
public void info(String message) {
log.log(callerFQCN, Level.INFO, message, null);
}
...
}
就是封装了一个org.apache.log4j.Logger,所有的操作调用log4j的log完成
初始化的代码在抽象类Log中
public abstract class Log {
private static ILogFactory defaultLogFactory = null;
static {
init();
}
static void init() {
if (defaultLogFactory == null) {
try {
Class.forName("org.apache.log4j.Logger");
Class<?> log4jLogFactoryClass = Class.forName("com.jfinal.log.Log4jLogFactory");
defaultLogFactory = (ILogFactory)log4jLogFactoryClass.newInstance(); // return new Log4jLogFactory();
} catch (Exception e) {
defaultLogFactory = new JdkLogFactory();
}
}
}
...
}
如果可以加载log4j的jar包,就使用log4j,否则使用JdkLog
在configConstant中配置即可
@Override
public void configConstant(Constants me) {
...
me.setLogFactory(new Slf4jLogFactory());
...
}
其中Slf4jLogFactory类直接使用了cn.dreampie的代码,表示感谢,maven如下
<dependency>
<groupId>cn.dreampie</groupId>
<artifactId>jfinal-slf4j</artifactId>
<version>0.1</version>
</dependency>
在此之前需要了解以下日志框架体系,日志框架体系介绍
从上面已经看到,日志门面使用的是slf4j,便于修改,但是底层的日志使用什么实现呢?log4j最新的一版是2012的,太老了直接淘汰,查了下比较常用的是log4j2和logback,从网上查到的资料个人感觉log4j2好用点,就决定使用log4j2,需要一共四个依赖.
<!--slf4j及log4j日志-->
<!--门面-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!--桥接器:告诉slf4j使用Log4j2-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!--具体实现,log4j2-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j2.version}</version>
</dependency>
<log4j2.version>2.9.1</log4j2.version>
<!--不能升级为1.8.*,log4j2的2.9.1版本依赖1.7.25,使用1.8提示No SLF4J providers were found-->
<slf4j.version>1.7.25</slf4j.version>
注意:slf4j1.8.*
与1.7.*
获取桥接器的方式不一致,log4j2的2.9.1
版本只实现了slf4j1.7.*
版本的桥接器.若修改slf4j版本为1.8.*
则不兼容
由于日志选择使用slf4j+log4j2,其实配置就是配置log4j2,网上关于如何配置log4j2的文章很多,都可以查到.
我配置的时候遇到一个坑,log4j2有两种模式,一种strict
,一种非strict
,strict模式是严格按照xsd标准的配置文件,当时觉得strict模式符合xsd标准,idea也不会报error,就尽力想使用strict模式配置,后来发现一些功能配置实现不了,而且网上的文章多数都是使用非strict模式配置,最后就放弃了,决定使用非strict模式配置,于是idea一打开log4j2.xml文件,就全是error,真是丑
当时下定决心修改日志框架是因为要让日志打印sql语句,最后该功能当然是实现了,不过使用的并不是文章开头链接中提到的方法,而是—–>druid,下一篇分享写下如何配置druid