日志框架-JCL、SLF4J日志门面(学习记录四)

1、简单介绍-JCL

JCL( Jakarta Commons Logging ),是 Apache 提供的一个 通用日志 API 。用户可以自由选择第三方的日志组件作为具体实现,像 Log4j 或 JDK 自带的 JUL 。

JCL的原则:如果有log4j优先使用log4j,没有任何的第三方框架就使用JUL。

面向接口开发,不再依赖具体的实现类,可以根据实际需求,灵活的切换日志框架。统一的 API,统一的配置管理便于项目日志的维护工作。

JCL 有两个基本的抽象类:Log(日志记录器)、LogFactory(日志工厂,负责创建 Log 实例)。

1.1、案列

1.依赖:

<dependencies>
    <!-- jcl日志门面 -->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <!-- 单元测试 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

2.代码:

public class JCLTest {

    @Test
    public  void  test01(){
        // JCL使用原则:有Log4j则优先使用,没有任何第三方日志框架则默认使用JUL
        Log log = LogFactory.getLog(JCLTest.class);
        log.info("info信息");
    }
}

3.运行结果:没有第三方框架,可以看出使用了 JDK 的 JUL 日志框架。

六月 05, 2023 12:01:58 上午 com.xb.JCLTest test01
信息: info信息

4.引入其他框架依赖:log4j的依赖

<!-- log4j日志框架 -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

5.创建配置: log4j.properties 文件 ,放在resources目录下

#配置日志级别,引用控制器
log4j.rootLogger=INFO,console
#配置控制台输出器
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}] [%-5p] [%t] [%-4rms] [%c#%M-%L] %m%n

6. 其他代码不变,查看日志信息:使用了log4j框架输出日志信息

[2023-06-05 00:12:44.642] [INFO ] [main] [0   ms] [com.xb.JCLTest] test01 20 info信息

 2、介绍-SLF4j

背景:在log4j开发出来出来之后,log4j就受到了广大开发者的爱好,纷纷开始使用log4j,但是后来 log4j的创始人跟apache因为一些矛盾从apache辞职自己去创业了,创始人为了给自己的公司打出一点名声,所以就基于log4j又开发出了一个新的日志框架 logback,logback不管是性能还是功能都比log4j强,但是却很少人使用, 因为jcl门面不支持logback,所以这个创世人又设计出了slf4j,slf4j支持市面上所有主流的日志框架;所以目前为止,使用最多的就是slf4j了; 后来 apache又基于 logback 的源码 设计出了 log4j2 日志,性能上log4j2比logback更胜一筹,并且log4j2既是日志框架,也是门面技术,但是log4j2的门面技术很少人使用,大多还是使用slf4j;

介绍:主要是为了给 Java 日志访问提供一套标准、规范的 API 框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如 Log4j 或 Logback 等。

        SLF4J 自身也提供了功能较为简单的实现,但是一般很少用到。对于一般的 Java 项目而言,日志框架会选择 slf4j-api 作为门面,配上具体的实现框架,中间使用桥接器完成桥接。所以 SLF4J 最重要的两个功能就是对于日志框架的绑定以及日志框架的桥接

2.1、 日志级别

只输出级别不低于设定级别的日志信息。

trace:日志追踪信息

debug:日志详细信息

info(默认):日志关键信息

warn:日志警告信息

error:日志错误信息

2.2、入门案例

导入依赖:

<dependencies>
        <!-- slf4j核心依赖 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <!-- slf4j自带的简单日志实现 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.25</version>
        </dependency>
        <!-- 单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!--设置编译版本1.8-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

代码:在没有引入其他的依赖就使用的是slf4j自带的日志框架

@Test
    public void test01(){
        // 没有集成其它日志实现框架的话,使用自带的简单日志实现框架(slf4j-simple)
        Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
        logger.trace("trace追踪信息");
        logger.debug("debug详细信息");
        logger.info("info关键信息");
        logger.warn("warn警告信息");
        logger.error("error错误信息");
        //动态拼接使用占位符
        logger.info("学生信息:姓名-{};年龄-{}", name, age)
    }

运行结果:

[main] INFO com.xb.Slf4jTest - info关键信息
[main] WARN com.xb.Slf4jTest - warn警告信息
[main] ERROR com.xb.Slf4jTest - error错误信息

2.3、动态打印

代码:占位符{}

@Test
public void test02() {
    Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
    String name = "李四";
    int age = 23;
    // 字符串拼接,麻烦、可读性差
    //logger.info("学生信息:姓名-" + name + ";年龄-" + age + "");
    // 动态信息打印,使用占位符的形式来代替字符串的拼接
    logger.info("学生信息:姓名-{};年龄-{}", name, age);
}

运行结果:

[main] INFO com.xb.Slf4jTest - 学生信息:姓名-李四;年龄-23

 2.4、异常信息打印

代码:

    @Test
    public void test03() {
        Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
        try {
            Class.forName("Student");
        } catch (ClassNotFoundException e) {
            logger.info("异常信息:", e);
        }
    }

运行结果:

[main] INFO com.xb.Slf4jTest - 异常信息:
java.lang.ClassNotFoundException: Student
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:264)
	at com.xb.Slf4jTest.test03(Slf4jTest.java:42)
....

2.5、日志集成

日志集成分为三种情况:

(1)没有绑定任何日志实现的基础上面,门面技术slf4j是不能够实现任何功能的。包括自带的slf4j-simpl官方提供的也必须导入相应的jar包配合使用。

(2)logback和simple(包括nop-禁止打印日志)都是slf4j时间线出现之后提供的日志实现,所以API完全遵循slf4j设计,使用只需要导入对应的jar包即可。

(3)log4j和JUL时间线是在slf4j之前的,要配合使用就必须通过适配桥接技术,完成与日志门面的连接。

注意: 在 SLF4J 环境下,若同时导入多个日志实现框架,默认使用先导入的。在实际应用中,一般只集成一种日志实现。

2.5.1、集成 logback

导入依赖:

        <!-- 引入logback依赖-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

代码:

@Test
    public void test04() {
        Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
        try {
            Class.forName("Student");
        } catch (ClassNotFoundException e) {
            logger.info("异常信息:", e);
        }
    }

运行结果:

SLF4J: Found binding in [jar:file:/E:/yc_maven/work/repository/org/slf4j/slf4j-simple/1.7.25/slf4j-simple-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
16:19:39.481 [main] INFO com.xb.Slf4jTest - 异常信息:
java.lang.ClassNotFoundException: Student
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:264)
	at com.xb.Slf4jTest.test03(Slf4jTest.java:42)

2.5.2、集成log4j-桥接模式

导入依赖:这里加入的是适配,不是桥接

        <!-- 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>

代码:

   @Test
    public void test05(){
        // 没有集成其它日志实现框架的话,使用自带的简单日志实现框架(slf4j-simple)
        Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
        logger.trace("trace追踪信息");
        logger.debug("debug详细信息");
        logger.info("info关键信息");
        logger.warn("warn警告信息");
        logger.error("error错误信息");

    }

配置文件:使用log4j的配置文件 

#配置日志级别,引用输出器
log4j.rootLogger=INFO,console

########## 控制台输出器 ##########
#配置控制台输出器
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}] [%-5p] [%t] [%-4rms] [%c] %M %L %m%n

运行结果:

[2023-06-06 16:32:51.825] [INFO ] [main] [1   ms] [com.xb.Slf4jTest] test01 22 info关键信息
[2023-06-06 16:32:51.828] [WARN ] [main] [4   ms] [com.xb.Slf4jTest] test01 23 warn警告信息
[2023-06-06 16:32:51.828] [ERROR] [main] [4   ms] [com.xb.Slf4jTest] test01 24 error错误信息

2.5.3、集成JUL

依赖:

        <!-- JUl适配slf4j-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jdk14</artifactId>
            <version>1.7.25</version>
        </dependency>

代码:

   @Test
    public void test05(){
        // 没有集成其它日志实现框架的话,使用自带的简单日志实现框架(slf4j-simple)
        Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
        logger.trace("trace追踪信息");
        logger.debug("debug详细信息");
        logger.info("info关键信息");
        logger.warn("warn警告信息");
        logger.error("error错误信息");
    }

结果:可以看出是JUL日志框架的输出风格

六月 06, 2023 4:37:37 下午 com.xb.Slf4jTest test01
信息: info关键信息
六月 06, 2023 4:37:37 下午 com.xb.Slf4jTest test01
警告: warn警告信息
六月 06, 2023 4:37:37 下午 com.xb.Slf4jTest test01
严重: error错误信息

 现在项目使用的是log4j,如何将项目框架转换成为logback?

(1)注释掉log4j依赖

(2)引入slf4j门面依赖和logback依赖

(3)此时代码编译会报错,继续引入log4j的桥接依赖,完成

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>log4j-over-slf4j</artifactId>
    <version>1.7.25</version>
</dependency>

注意:桥接器和适配器不能同时存在。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值