jck28-桔子-日志框架,日志门面 - 学习笔记

一 日志框架和日志门面

  1. 日志框架/日志实现:
    JUL: Java util logging
    log4j: Log for java
    logback:
    log4j2:
  2. 日志门面
    JCL: java commong logging
    SLF4J: simple logging facade for java
  3. 出现顺序
    log4j → JUL → JCL(门面)slf4j(门面) → logback → slf4j2

二 日志框架的使用

1. JUL日志框架

  • 组件
    Logger
    Handder
    Formatter

  • logger之日记录器,入口Logger.getLogger

        Logger logger = Logger.getLogger(Dailylog.class);
        logger.info("info log");
        logger.debug("debug log");

2. log4j日志框架

  • 组件(对应于JUL的组件)
    Loggers<==>Logger
    Handder<==>Appender
    Formatter<==>Layout

  • logger之日记录器,入口Logger.getLogger

        Logger logger = Logger.getLogger(Dailylog.class);
        logger.info("info log");
        logger.debug("debug log");
  • log4j的配置文件
    路径/文件名: Resouces > log4j.properties
    逗号隔开:log4j.rootLogger = 日志级别,appenderName1, appenderName2
    layout使用中最多的就是PatternLayout自定义输出格式,格式定义在ConversionPattern中实现:
log4j.rootLogger=INFO, stdout, logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} <%p> %c %m%n

日志格式的占位符意义:

%d 当前服务器时间
%c category
%m 相应的消息
%n 换行
%p 日志级别
%r 自开始执行到当前日志打印的时间
%10r  十个字符,空格补齐,右对齐  %-10r  十个字符,左对齐
  • FileAppender

  • RollingFileAppender

  • DailyRollingFileAppender

log4j.rootLogger=INFO, logfile
log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.file=test-output/log4j_log/myLog4j.log
log4j.appender.logfile.encoding=UTF-8
log4j.appender.logfile.Append=true 
log4j.appender.logfile.DatePattern='.'yyyy-MM-dd  //按照日拆分,如果'.'yyyy-MM-dd HH-mm-ss就是按秒拆分
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} <%p> %c %m%n

三 日志门面的使用

  1. 日志门面统一了不同日志框架的不同API,写了一套统一的API,它本身不实现日志记录功能,自己只是提供了统一的接口,如果使用一款日志门面,具体的实现框架可以是多个框架。
  • logger入口统一:LogFactory.getLogger(xxx.class)

  • appenders

  • Layout

  1. 日志门面技术
  • 统一入口接入API, LogFactory.getLogger(xxx.class),不再依赖具体的日志框架
package com.learn.log;

import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class NewLogTest {
    //测试门面slf4j
    //import里面没有指定具体用哪个log框架实现的
    //具体log框架:
        // 如果dependency里面有log4j就用log4j,
        // 如果没有依赖,就用JUL(JDK自带的log框架)
    @Test
    public void logTest1(){
        Logger logger = LoggerFactory.getLogger(NewLogTest.class);
        logger.info("slf4j");
    }
}
  • 统一日志level
    trace
    debug
    info
    warn
    error

  • 日志门面技术和具体的日志实现(框架)组合时候,由于出场时间的问题,在日志门面技术之前出现的日志实现(框架),需要适配器
    技术出场顺序:log4j → JUL → JCL(门面)slf4j(门面) → slf4j2

  1. 日志门面,slf4j,有三种情况,对日志实现进行绑定
  • 在没有任何日志实现绑定的情况下,是不能实现任何功能的,须得加上slf4j-simple的依赖
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.25</version>
        </dependency>
  • logback,simple,nop都是出现在slf4j时间线后面的技术,只需要导入相应日志实现/框架的依赖包,就可以实现slf4j无缝衔接

  • log4j和JUL都是slf4j日志门面时间线之前的,API不符合slf4j的设计,所以,需要适配器来与日志门面衔接使用

  • dependency里面加了多个日志实现,先绑定哪个就用哪个,所以我们添加dependency的收就加一个就行

  1. slf4j与之前的日志框架适配的依赖,也就是适配器
  • 与JUL适配,除了添加slf4j的依赖,还需要添加适配器:
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jdk14</artifactId>
            <version>2.0.9</version>
        </dependency>
*JUL是JDK内置的,本身不需要添加依赖*
  • 与log4j适配,除了添加slf4j的依赖,还需要添加: log4j和适配器:
        <!-- log4j自己的依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.13</version>
        </dependency>
        <!-- log4j的适配器-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>

四 最新的日志框架/日志实现技术logckback

  1. logback是log4j的改良版,跟log4j是同一个创始人设计的,完全符合slf4j日志门面
  2. logback分三个模块, logback-core, logback-classic, logback-access, 其中logback-core是其他两个模块的基础模块
  3. 组件:
    Logger
    Appender
    Layout封装在encoder中
%-10level 十个字符,左对齐
%d{yyyy-MM-dd HH:mm:ss.SSS} 日期
%c 当前类全限定名
%M 当前执行日志的方法名
%L 行号
%thread 线程名称
%m或者%msg 日志信息
%n 换行
  1. 配置文件
    logback.groovy
    logback-test.xml
    logback.xml
    我写了两个appender
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<property name="pattern" value="[%-5level] %d{yyyy-MM-dd} %c %M %L %thread %m%n"></property>
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <!--
        System.err是红色
        System.out是黑色
        -->
        <target>
            System.out
        </target>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>

    <appender name="fileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <append>true</append>
            <maxHistroy>5</maxHistroy>
            <minIndex>1</minIndex>
            <maxIndex>5</maxIndex>
            <totalSizeGap>50MB</totalSizeGap>
            <!--必须包含%i和%d-->
            <fileNamePattern>test-output/logback_log/myLogback.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>1MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>

    </appender>


    <!--root logger的配置,level和appenders-->
    <root level="ALL">
        <appender-ref ref = "consoleAppender"></appender-ref>
        <appender-ref ref = "fileAppender"></appender-ref>
    </root>
</configuration>
  1. 依赖
        <!-- logback不需要适配器,只需要添加自己的两个依赖包即可-->
        <!--logback-core是classic的基础模块,根据maven的依赖传递属性,不需要额外添加-->
        <dependency>
            <groupId>com.hynnet</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.3</version>
        </dependency>
  1. logger入口没有变化
package com.learn.log;

import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class NewLogTest {
    //测试门面slf4j
    //import里面没有指定具体用哪个log框架实现的
    //具体log框架:
        // 如果dependency里面有log4j就用log4j,
        // 如果没有依赖,就用JUL(JDK自带的log框架)
        //代码不需要改动,只需要修改依赖包就可以,这就是日志门面的好处
    @Test
    public void logTest1(){
        Logger logger = LoggerFactory.getLogger(NewLogTest.class);
        logger.info("slf4j");
        String name = "harry";int age = 10;
        logger.info("学生姓名:{};学生年龄:{}",name,age);
    }
}

1 个赞