日志
  l2lUlbO2qhDY 2023年11月01日 27 0

前言:日志通常打印在控制台或者日志文件。打印需要考虑格式、日志级别、性能等问题,手动实现起来比较麻烦,为此衍生出一大批的日志打印框架比如JUL(java util logging)、logback、log4j、log4j2。

一、日志实现

1.JUL(Java util logging)

1.1 入门案例

JUL是JDK提供的日志打印工具,使用起来比较简单,不需要引入外部依赖,下面就是最简单的一个入门案例。

    @Test
    public void testJUL() {
// 获取Logger对象 Logger logger
= Logger.getLogger("com.xxx.log.JULLogTest"); logger.info("hello JUL"); }

1.2 概念

JUL引入了很多重要的概念,后续的其他框架也进行了引用。

Logger:被称为日志记录器,应用程序通过获取Logger对象,并调用其方法完成日志打印。

Appender:也被称为Handler,一个Logger对象可以关联一个或多个Appender对象,Logger会将日志交给Appender处理,不同的Appender实现打印的日志位置也不同,比如可以将日志打印至控制台、文件、数据库等。

Layout:负责对日志数据进行格式化。

Level:日志级别

JUL中的Logger(后面的日志实现也都遵循此规律)存在父子关系,在程序启动时,会创建一个RootLogger,它是所有Logger的根。其他的Logger默认会继承RootLogger的Appender、Layout以及日志打印级别,这一点非常重要。在开发中我们一般只会在配置文件中配置RootLogger,其他的Logger继承它就行。至于其他Logger,它们的继承关系通过包的路径来关联,比如com.example的Logger继承自com的Logger。

2.Log4j

log4j是log for java的简称,是Apache开源的一款日志打印框架,虽然其存在安全问题,已经很少使用,但是他的升级版本Log4j2,在安全和性能上都有了很大的提升,是现在的主流日志框架,因此还是有必要了解下。

入门案例

1. 引入log4j依赖

 <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
  </dependency>

2. 编写配置文件

log4j会默认扫描classpath下的配置文件log4j.xml或log4j.properties,如果扫描不到配置文件,会报错"No appenders could be found for logger"。

#指定日志的输出级别与输出端
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 [%t] %-5p [%c] - %m%n

3.编写Java代码

    public static void main(String[] args) {
        Logger logger = Logger.getLogger(Log4jTest.class);
        logger.fatal("fatal...");
        logger.error("error...");
        logger.warn("warn...");
        logger.info("info...");
        logger.debug("debug...");
        logger.trace("trace...");
    }

4.控制台输出

2022-10-23 16:56:52,478 [main] FATAL [org.log.Log4jTest] - fatal...
2022-10-23 16:56:52,478 [main] ERROR [org.log.Log4jTest] - error...
2022-10-23 16:56:52,479 [main] WARN  [org.log.Log4jTest] - warn...
2022-10-23 16:56:52,479 [main] INFO  [org.log.Log4jTest] - info...

组件

与jul类似,log4j也包含三个重要的组件:Logger、Appender以及Layout,其功能也类似,这里不再赘述。

配置文件

log4j的配置文件主要就是配置上面提到的Logger、Appender以及Layout组件。

Logger组件的配置:可按照下面的方式配置rootLogger,首先是日志级别,然后是Appender的名称,可以配置多个Appender,之间用逗号隔开。

log4j.rootLogger=INFO,Console,File

Appender组件配置:根据输出的位置不同,选择不同的Appender。输出至console,选择org.apache.log4j.ConsoleAppender,输出至文件,选择org.apache.log4j.DailyRollingFileAppender。log4j.appender.xxx,其中xxx代表在Appender名称,与Logger配置中的名称一致              log4j.appender.Console=org.apache.log4j.ConsoleAppender

Loayout组件配置:配置文件的输出格式,一个Appender配置一个与之对应的Layout。

log4j.appender.Console.layout=org.apache.log4j.PatternLayout

log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n

3.Logback

Logback是Log4j的创始人开发的另外一款日志打印框架,性能比Log4j好,也是Spring底层使用的默认日志打印实现。同时它完整实现了slf4j的API,可以轻松和slf4j对接。

入门案例

1.引入依赖

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

2.配置文件编写

logback会依次读取以下类型配置文件:logback.groovy、logback-test.xml、logback.xml。如果均不存在会采用默认配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--日志输出格式-->
    <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %c [%thread]%-5level %msg%n"/>

    <!-- Appender: 设置日志信息的去向,常用的有以下几个
        ch.qos.logback.core.ConsoleAppender (控制台)
        ch.qos.logback.core.rolling.RollingFileAppender (文件大小到达指定尺寸的时候产生一个新文件)
        ch.qos.logback.core.FileAppender (文件)
    -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!--输出流对象 默认 System.out 改为 System.err-->
        <target>System.err</target>
        <!--日志格式配置-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>

    <!--用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。 -->
    <root level="ALL">
        <appender-ref ref="console"/>
    </root>
</configuration>

3.代码编写

    public static void main(String[] args) {
        Logger LOGGER = LoggerFactory.getLogger(LogbackTest.class);
        //打印日志信息
        LOGGER.error("error");
        LOGGER.warn("warn");
        LOGGER.info("info");
        LOGGER.debug("debug");
        LOGGER.trace("trace");
    }

4.测试

2022-10-23 17:47:45.044 org.log.LogbackTest [main]ERROR error
2022-10-23 17:47:45.046 org.log.LogbackTest [main]WARN  warn
2022-10-23 17:47:45.047 org.log.LogbackTest [main]INFO  info
2022-10-23 17:47:45.047 org.log.LogbackTest [main]DEBUG debug
2022-10-23 17:47:45.047 org.log.LogbackTest [main]TRACE trace

4.Log4j2

Log4j2是Log4j的升级版,性能也比logback更强,是目前最主流的日志实现框架。

入门案例

1.添加依赖

<!-- Log4j2日志API -->
<
dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.11.1</version> </dependency> <!-- Log4j2 日志实现 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.11.1</version> </dependency>

 2.配置文件

log4j2会默认扫描classpath下的log4j2.xml文件

 
   
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" monitorInterval="5">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L%m%n"/>
</Console>
</Appenders>

<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

3.编写Java代码

    public static void main(String[] args) {
        Logger LOGGER = LogManager.getLogger(Log4j2Test.class);
        LOGGER.fatal("fatal");
        LOGGER.error("error");
        LOGGER.warn("warn");
        LOGGER.info("info");
        LOGGER.debug("debug");
        LOGGER.trace("trace");
    }

4.测试

19:26:53.661 [main] [FATAL] org.log.Log4j2Test:10fatal
19:26:53.670 [main] [ERROR] org.log.Log4j2Test:11error
19:26:53.670 [main] [WARN ] org.log.Log4j2Test:12warn
19:26:53.670 [main] [INFO ] org.log.Log4j2Test:13info

异步日志

Log4j2支持异步打印日志,这也使得其性能得到很大提升。一共有两种实现方式:一个是通过AsyncAppender,一个是通过AsyncLogger。在使用异步日志之前需要引入依赖:

<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.3.4</version>
</dependency>

二、日志门面

与日志实现不同,日志门面是提供给程序员的一套API,开发时,只需要面向接口编程,可以在不改变源代码的情况下,更换日志实现。这一点,有点类似于JDBC接口和具体的数据库实现之间的关系。

1.JCL(Jakarta Commons Logging) 

是Apace提供的一套日志打印API接口(日志门面),开发人员可以面向JCL接口编程,JCL会自动扫描具体的日志实现类,实现业务代码和具体的日志打印实现类解耦。目前已经基本被淘汰。

2.slf4j(simple logging facade for java)

SLF4J是目前市面上最流行的日志门面,现在的项目中,基本上都是使用SLF4J作为日志系统。SLF4J主要提供两大功能:绑定日志实现和日志桥接。

绑定日志实现

绑定日志实现简单来说就是使用slf4j作为日志门面,使用其他的日志系统作为实现,开发人员面向slf4j接口编程即可。需要注意的是,有的日志实现早于slf4j出现,并没有实现slf4j接口,针对这种场景,slf4j提供了对应的适配器。具体的依赖和适配关系如下图:

使用时,需要引入slf4j-api和相应的实现(适配器),slf4j会自动扫面日志实现,决定使用哪个日志实现。

日志桥接

在开发中,还有一种常见的场景,就是不同的项目使用的日志系统可能不一样,这样维护起来不方便。为此slf4j提出日志桥接的概念,可以将所有的日志系统统一于slf4j,主要步骤如下:

1. 先去除之前老的日志框架的依赖

2. 添加SLF4J提供的桥接组件

3. 为项目添加SLF4J的具体实现

依赖关系图如下:

 

 三、SpringBoot中的日志系统

springboot 默认使用SLF4J作为日志门面,logback作为日志实现来记录日志。

可以看到SpringBoot通过引入桥接器,将log4j、jul都转换为SLF4J,最终logback作为日志实现。当然,要让上面的想法生效,必须排除掉log4j、jul的实现依赖。

如果要使用log4j2作为实现,只需要排除logback依赖,添加log4j2依赖即可

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
    <!--排除logback-->
    <exclusion>
      <artifactId>spring-boot-starter-logging</artifactId>
      <groupId>org.springframework.boot</groupId>
    </exclusion>
  </exclusions>
 </dependency>
<!-- 添加log4j2 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

上一篇: Lists.partition 下一篇: 缓存 - 方法注解组件
  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  2Vtxr3XfwhHq   2024年05月17日   55   0   0 Java
  Tnh5bgG19sRf   2024年05月20日   113   0   0 Java
  8s1LUHPryisj   2024年05月17日   48   0   0 Java
  aRSRdgycpgWt   2024年05月17日   47   0   0 Java