https://www.hoshino.asia/archives/hutool

概述

由来

准确的说,Hutool-log只是一个日志的通用门面,功能类似于Slf4j。既然像Slf4j这种门面框架已经非常完善,为何还要自己做一个门面呢?下面我列举实践中遇到的一些问题:

已有门面存在问题

  1. log对象创建比较复杂

很多时候我们为了在类中加日志不得不写一行,而且还要去手动改XXX这个类名

private static final Logger log = LoggerFactory.getLogger(XXX.class);
  1. 对于附带Exception参数的方法,并不支持变量。

Slf4j中我最喜欢的形式,这样既省去了麻烦的isInfoEnabled()的判断,还避免了拼接字符串:

log.info("我在XXX 改了 {} 变量", "name");

但是这种情况下就无法使用变量模式:

log.error("错误消息", e);

特点

  1. Logfactory.get方法不再需要(或者不是必须)传入当前类名,会自动解析当前类名

  2. log.xxx方法在传入Exception时同时支持模板语法。

  3. 不需要桥接包而自动适配引入的日志框架,在无日志框架下依旧可以完美适配JDK Logging。

  4. 引入多个日志框架情况下,可以自定义日志框架输出。

原理

Hutool-log采用动态自动适配模式,它会自动检测引入的日志框架包从而将日志输出到此框架。 比如我们在项目中引入Log4j的包,Hutool-log会自动检测到此包的存在,并将日志输出到log4j。如果没有引入任何日志框架,会将日志输出到JDK Logging中。

因此,Hutool-log并没有统一的配置文件,如果你引入任何一种日志框架,使用此框架的配置文件即可。

Hutool-log对于日志框架的监测顺序是: Slf4j(Logback) > Log4j > Log4j2 > Apache Commons Logging > JDK Logging > Console

当然,如果只是引入Slf4j-API,而没有引入任何实现,Slf4j将被跳过。

关于日志框架监测的核心代码请参阅:LogFactory.create

使用

常规使用

Hutool-log的使用与一般日志框架并无区别,调用LogFactory.get()即可简单获取Log实现对象。

Log log = LogFactory.get();

log.debug("This is {} log", Level.DEBUG);
log.info("This is {} log", Level.INFO);
log.warn("This is {} log", Level.WARN);

Exception e = new Exception("test Exception");
log.error(e, "This is {} log", Level.ERROR);

通常我们需要在类中定义日志为private static final Log log = LogFactory.get();以获得更好的性能。

自定义日志实现

有的时候,我们需要自定义日志框架输出,这是我们就需要调用LogFactory.setCurrentLogFactory方法来定义全局的日志实现。

// 自动选择日志实现
Log log = LogFactory.get();
log.debug("This is {} log", "default");
Console.log("----------------------------------------------------------------------");

//自定义日志实现为Apache Commons Logging
LogFactory.setCurrentLogFactory(new ApacheCommonsLogFactory());
log.debug("This is {} log", "custom apache commons logging");
Console.log("----------------------------------------------------------------------");

//自定义日志实现为JDK Logging
LogFactory.setCurrentLogFactory(new JdkLogFactory());
log.info("This is {} log", "custom jdk logging");
Console.log("----------------------------------------------------------------------");

//自定义日志实现为Console Logging
LogFactory.setCurrentLogFactory(new ConsoleLogFactory());
log.info("This is {} log", "custom Console");
Console.log("----------------------------------------------------------------------");

默认的,在未发现任何第三方日志的情况下,检查logging.properties文件是否在classpath中存在(鉴定用户是否想用JDK Logging),如果没有这个配置文件,默认是按照Hutool预定义规则打印到控制台。

日志工厂-LogFactory

介绍

Hutool-log做为一个日志门面,为了兼容各大日志框架,一个用于自动创建日志对象的日志工厂类必不可少。

LogFactory类用于灵活的创建日志对象,通过static方法创建我们需要的日志对象,主要功能如下:

  • LogFactory.get 自动识别引入的日志框架,从而创建对应日志框架的门面Log对象(此方法创建一次后,下次再次get会根据传入类名缓存Log对象,对于每个类,Log对象都是单例的),同时自动识别当前类,将当前类做为类名传入日志框架。

  • LogFactory.createLog 与get方法作用类似。但是此方法调用后会每次创建一个新的Log对象。

  • LogFactory.setCurrentLogFactory 自定义当前日志门面的日志实现类。当引入多个日志框架时,我们希望自定义所用的日志框架,调用此方法即可。需要注意的是,此方法为全局方法,在获取Log对象前只调用一次即可。

使用

获取当前类对应的Log对象:

//推荐创建不可变静态类成员变量
private static final Log log = LogFactory.get();

如果你想获得自定义name的Log对象(像普通Log日志实现一样),那么可以使用如下方式获取Log:

private static final Log log = LogFactory.get("我是一个自定义日志名");

自定义日志实现

//自定义日志实现为Apache Commons Logging
LogFactory.setCurrentLogFactory(new ApacheCommonsLogFactory());

//自定义日志实现为JDK Logging
LogFactory.setCurrentLogFactory(new JdkLogFactory());

//自定义日志实现为Console Logging
LogFactory.setCurrentLogFactory(new ConsoleLogFactory());

自定义日志工厂(自定义日志门面实现)

LogFactory是一个抽象类,我们可以继承此类,实现createLog方法即可(同时我们可能需要实现Log接口来达到自定义门面的目的),这样我们就可以自定义一个日志门面。最后通过LogFactory.setCurrentLogFactory方法装入这个自定义LogFactory即可实现自定义日志门面。

PS 自定义日志门面的实现可以参考cn.hutool.log.dialect包中的实现内容自定义扩展。 本质上,实现Log接口,做一个日志实现的Wrapper,然后在相应的工厂类中创建此Log实例即可。同时,LogFactory中还可以初始化一些启动配置参数。

疑惑解答

问:

程序中出现[WARN] Can not find [logging.properties], use [%JRE_HOME%/lib/logging.properties] as default!这行警告,请问这个问题如何解决?

答:

这是因为你没有引入任何第三方日志框架。Hutool默认会使用JDK Logging做为其日志实现。出现这句话的意思是你没有在你的ClassPath下放logging.properties(JDK Logging的配置文件),系统默认读取JDK目录下的默认配置文件。你可以考虑在ClassPath下放一个logging.properties(就是src/main/resources)下。

配置文件模板见:https://gitee.com/dromara/hutool/blob/v5-master/hutool-log/src/test/resources/logging.properties

其它日志框架的配置文件模板见:https://gitee.com/dromara/hutool/tree/v5-master/hutool-log/src/test/resources

注意 在新版的Hutool中会自动检测logging.properties存在与否,如果不存在这个配置文件,将跳过JDK-Logging从而使用Console-log(命令行打印日志)

静态调用日志-StaticLog

由来

很多时候,我们只是想简单的使用日志,最好一个方法搞定,我也不想创建Log对象,那么StaticLog或许是你需要的。

使用

StaticLog.info("This is static {} log.", "INFO");

同样StaticLog提供了trace、debug、info、warn、error方法,提供变量占位符支持,使项目中日志的使用简单到没朋友。

StaticLog类中同样提供log方法,可能在极致简洁的状况下,提供非常棒的灵活性(打印日志等级由level参数决定)

与LogFactory同名方法

假如你只知道StaticLog,不知道LogFactory怎么办?Hutool非常贴心的提供了get方法,此方法与Logfactory中的get方法一样,同样可以获得Log对象。

Ciallo~(∠・ω< )⌒☆