Java日志总结

开发中,日志记录是不可或缺的一部分,应用日志的记录主要用于:记录操作轨迹数据、监控系统运行情况、系统故障定位问题,日志的重要性不言而喻,想要快速定位问题,日志分析是个重要的手段,Java也提供了多种日志框架来进行有效的日志管理。本文将探讨Java常用的日志框架以及使用案例。

一、发展历史

  • 1996: Log4j 1.x 由瑞士程序员CeKi Gülcü 发布
  • 2002: JDK 1.4 发布,包含 JUL(java.util.logging,位于java.logging模块下),是 JDK 官方自带的日志框架。JUL 性能很差,使用比较少。
  • 2002: Apache推出了Jakarta Commons Logging(简称JCL)日志接口
  • 2010: Slf4j 发布
  • 2009: Logback 发布
  • 2014: Log4j2 发布

二、日志框架

现有的一些日志框架:

  • 日志实现:JUL(java.util.logging)、logback、log4j、log4j2
  • 日志门面:JCL(Jakarta Commons Logging)、Slf4j(Simple Logging Facade for Java)

在这里插入图片描述

1.Log4j

官方网站: http://logging.apache.org/log4j/1.2
Log4j 是 Apache 的一个开源项目,创始人 Ceki Gulcu。是 Java 领域资格最老,应用最广的日志工具。Log4j 中有三个主要组件:

  • loggers(记录器) - 负责接收并记录日志信息。
  • appenders(输出器) - 负责发布日志信息,定义了日志信息的目的地(如控制台、文件、数据库等)。
  • layouts(布局) -负责定义日志输出的格式。
    这种解耦的设计使得Log4j非常灵活,可以很容易地根据项目的需求进行定制。

1.1 log4j使用:

1).添加maven依赖

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

2).resources目录下创建log4j.properties文件(log4j支持两种配置文件格式:一种是XML格式的文件,一种是properties属性文件)

log4j.rootLogger=INFO,M,C,E
log4j.additivity.monitorLogger=false
# INFO级别文件输出配置
log4j.appender.M=org.apache.log4j.DailyRollingFileAppender
log4j.appender.M.File=/logs/info.log
log4j.appender.M.ImmediateFlush=false
log4j.appender.M.BufferedIO=true
log4j.appender.M.BufferSize=16384
log4j.appender.M.Append=true
log4j.appender.M.Threshold=INFO
log4j.appender.M.DatePattern='.'yyyy-MM-dd
log4j.appender.M.layout=org.apache.log4j.PatternLayout
log4j.appender.M.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} %p %l %m %n
# ERROR级别文件输出配置
log4j.appender.E=org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File=/logs/error.log
log4j.appender.E.ImmediateFlush=true
log4j.appender.E.Append=true
log4j.appender.E.Threshold=ERROR
log4j.appender.E.DatePattern='.'yyyy-MM-dd
log4j.appender.E.layout=org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} %p %l %m %n
# 控制台输出配置
log4j.appender.C=org.apache.log4j.ConsoleAppender
log4j.appender.C.Threshold=INFO
log4j.appender.C.layout=org.apache.log4j.PatternLayout
log4j.appender.C.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %l %m %n

appender配置常使用的类如下:

org.apache.log4j.ConsoleAppender(控制台)
org.apache.log4j.FileAppender(文件)
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

layouts常用配置类:

org.apache.log4j.HTMLLayout(以HTML表格形式布局)
org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)

layout格式化打印参数:

* log4j 采用类似 C 语言的 printf 函数的打印格式格式化日志信息,具体的占位符及其含义如下:
%m   输出代码中指定的日志信息
%p   输出优先级,及 DEBUGINFO%n   换行符(Windows平台的换行符为 "\n"Unix 平台为 "\n"%r   输出自应用启动到输出该 log 信息耗费的毫秒数
%c   输出打印语句所属的类的全名
%t   输出产生该日志的线程全名
%d   输出服务器当前时间,默认为 ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日 
HH:mm:ss}
%l   输出日志时间发生的位置,包括类名、线程、及在代码中的行数。如:
Test.main(Test.java:10)
%F   输出日志消息产生时所在的文件名称
%L   输出代码中的行号 
%%   输出一个 "%" 字符

* 可以在 % 与字符之间加上修饰符来控制最小宽度、最大宽度和文本的对其方式。如:
%5c     输出category名称,最小宽度是5,category<5,默认的情况下右对齐
%-5c    输出category名称,最小宽度是5,category<5"-"号指定左对齐,会有空格
%.5c    输出category名称,最大宽度是5,category>5,就会将左边多出的字符截掉,<5不
会有空格
%20.30c category名称<20补空格,并且右对齐,>30字符,就从左边交远销出的字符截掉

xml文件格式如下:

<?xml version="1.0" encoding="UTF-8"?>

<Configuration>

  <Appenders>

    <Appender>
      <Filters>
        <LevelRangeFilter minLevel="..." maxLevel="..." onMatch="..." onMismatch="..."/>
      </Filters>

      <PatternLayout pattern="..." charset="..."/>

      <Policies>
        <CronTriggeringPolicy schedule="..."/>
        <SizeBasedTriggeringPolicy size="..."/>
        <TimeBasedTriggeringPolicy />
      </Policies>
      
    </Appender>
    <Appender>
       ...
    </Appender>
  </Appenders>

  <Loggers>
    <Logger>
      <AppenderRef ref="...">
    </Logger>
    <Root>
      <AppenderRef ref="...">
    </Root>
  </Loggers>

</Configuration>

3) log4j日志打印测试

import org.apache.log4j.Logger;
public class Log4jTest {
    @Test
    public void testLog4j(){
        // 1.创建日志记录器对象,使用静态方法创建
        Logger logger = Logger.getLogger("com.example.logtest.Log4jTest");
        // 记录debug级别的信息
        logger.debug("This is debug message.");
        // 记录info级别的信息
        logger.info("This is info message.");
        // 记录error级别的信息
        logger.error("This is error message.");
    }
}

2.JUL

JUL全称Java util Logging是Java原生的日志框架,使用时不需要另外引用第三方类库,JUL主要用于小型应用程序中,其设计原理基于几个核心组件:

  • Logger:记录器,是应用程序访问日志系统的入口点。应用程序通过获取Logger对象,并调用其API来发布日志信息。Logger对象通常与特定的类或代码块相关联,以便能够精确地跟踪和记录日志。
  • Handler:也被称为Appenders,每个Logger都会关联一个或多个Handler。Handler负责处理Logger传递过来的日志信息,并将其发送到指定的目的地,如控制台、文件、网络上的其他日志服务或操作系统日志等。Handler的具体实现决定了日志记录的位置和方式。
  • Filter:过滤器,用于根据特定条件筛选日志信息。开发者可以根据需要定制哪些信息会被记录,哪些信息会被忽略,从而实现对日志信息的精细控制。
  • Level:日志的输出级别。每条日志消息都有一个关联的级别,如DEBUG、INFO、WARN、ERROR等。这些级别粗略地指导了日志消息的重要性和紧迫性。

JUL的配置相对简单,配置文件通常使用.properties或XML格式,虽然是JDK自带的日志库,JUL使用的并不广泛,原因是因为JUL早期存在性能问题,到JDK1.5上才有了不错的进步,但现在和Logback/Log4j2相比还是有所不如

2.1 测试案例

import java.util.logging.Level;
import java.util.logging.Logger;
public class JULTest {
    @Test
    public void testQuick(){
        // 1.创建日志记录器对象,使用静态方法创建
        Logger logger = Logger.getLogger("com.example.logtest.JULTest");
        // 2.日志记录输出
        logger.info("hello JUL");
        // 通用方法输出
        logger.log(Level.INFO, "info msg");
        // 通过占位符输出
        logger.log(Level.INFO, "name: {0},age: {1}", new Object[]{"zhangsan",20});
    }
}

2.2 日志级别

java.util.logging.Level中定义了7个日志的级别

// 关闭日志记录
public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle);
// 错误--最高的日志级别
public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle);
// 警告
public static final Level WARNING = new Level("WARNING", 900, defaultBundle);
// 消息(默认级别)
public static final Level INFO = new Level("INFO", 800, defaultBundle);
// 配置
public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle);
// 详细信息(少)
public static final Level FINE = new Level("FINE", 500, defaultBundle);
// 详细信息(中)
public static final Level FINER = new Level("FINER", 400, defaultBundle);
// 详细信息(多)-- 最低级的日志级别
public static final Level FINEST = new Level("FINEST", 300, defaultBundle);
// 启用所有消息日志
public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);

2.3 日志配置

如果我们没有添加配置,JUL默认的配置文件:JAVA_HOME/jre/lib/logging.properties

############################################################
#  	Default Logging Configuration File
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property.  
# For example java -Djava.util.logging.config.file=myfile
############################################################

############################################################
#  	Global properties
############################################################

# "handlers" specifies a comma separated list of log Handler 
# classes.  These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
## RootLogger使用的处理器
handlers= java.util.logging.ConsoleHandler

# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers.  For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
# RootLogger日志等级
.level= INFO

############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################
## 文件处理器
# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
## 控制台处理器
# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

# Example to customize the SimpleFormatter output format 
# to print one-line log message like this:
#     <level>: <log message> [<date/time>]
#
# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n

############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################

# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE

自定义日志级别及配置

@Test
public void test2() throws IOException {
// 1.获取日志记录器对象
Logger logger = Logger.getLogger("com.example.logtest.JULTest");

// 关闭系统默认配置
logger.setUseParentHandlers(false);
// 一、自定义配置日志级别

// 创建ConsoleHandler 控制台输出
ConsoleHandler consoleHandler = new ConsoleHandler();
// 创建简单格式转换对象
SimpleFormatter simpleFormatter = new SimpleFormatter();
// 进行关联
consoleHandler.setFormatter(simpleFormatter);
logger.addHandler(consoleHandler);
// 配置日志具体级别
logger.setLevel(Level.ALL);
consoleHandler.setLevel(Level.ALL);

// 二、输出到日志文件
FileHandler fileHandler = new FileHandler("d:/jul.log");
// 进行关联
fileHandler.setFormatter(simpleFormatter);
logger.addHandler(fileHandler);

// 日志记录输出
logger.severe("severe");
logger.warning("warning");
logger.info("info"); // 默认日志输出级别
logger.config("config");
logger.fine("fine");
logger.finer("finer");
logger.finest("finest");
}

2.4 日志对象Logger的父子关系

JUL中Logger对象存在父子关系,也就是父亲Logger的设置,同时能够作用于儿子,这种父子关系是通过树状结构包路径进行存储,如下:logger1的日志设置,对logger2也能生效。

@Test
    public void test3() throws Exception {
        // 日志记录器对象父子关系
        Logger logger1 = Logger.getLogger("com.fang");
        Logger logger2 = Logger.getLogger("com.fang.log");
        System.out.println(logger2.getParent() == logger1);
        // 所有日志记录器对象的顶级父元素  class为java.util.logging.LogManager
        System.out.println("logger2 parent:" + logger2.getParent() + ",name:" + logger2.getParent().getName());
        // 一、自定义日志级别
        // a.关闭系统默认配置
        logger1.setUseParentHandlers(false);
        // b.创建handler对象
        ConsoleHandler consoleHandler = new ConsoleHandler();
        // c.创建formatter对象
        SimpleFormatter simpleFormatter = new SimpleFormatter();
        // d.进行关联
        consoleHandler.setFormatter(simpleFormatter);
        logger1.addHandler(consoleHandler);
        // e.设置日志级别
        logger1.setLevel(Level.ALL);
        consoleHandler.setLevel(Level.ALL);
        // 测试日志记录器对象父子关系
        logger2.severe("severe");
        logger2.warning("warning");
        logger2.info("info");
        logger2.config("config");
        logger2.fine("fine");
        logger2.finer("finer");
        logger2.finest("finest");
    }

测试结果:

true
logger2 parent:java.util.logging.Logger@6ec8211c,name:com.fang
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
严重: severe
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
警告: warning
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
信息: info
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
配置: config
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
详细: fine
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
较详细: finer
五月 10, 2024 12:09:45 上午 com.example.logtest.JULTest testLogParent
非常详细: finest

3.Slf4j

Slf4J(Simple Logging Facade for Java)是一个用于Java的简单日志门面(Facade)主要是为了给Java日志访问提供一套标准、规范的API框架,它本身并不提供具体的日志实现,具体的实现可以交由其他日志框架,例如 log4j 、 logback、java.util.logging等。当然 Slf4J 自己也提供了功能较为简单的实现 slf4j-simple,但是一般很少用到。SLF4J 的作者就是 log4j 的作者 Ceki Gülcü,他宣称 SLF4J 比 log4j 更有效率,而且比 Apache Commons Logging (JCL) 简单、稳定。
官网:https://www.slf4j.org

3.1 Slf4j的官网架构图

在这里插入图片描述
上面架构图中可以看到,第一层是应用层,第二层即为slf4j提供的抽象接口:slf4j-api.jar,第三层的话蓝色的(2列5列6列)是日志的实现,而且是直接实现slf4j-api.jar相关接口,湖蓝色(3列4列)是适配层,与上面的slf4j-api接口以及第4层具体日志框架(log4j、jul)的适配。从上图也可以看到logback是直接实现了slf4j的接口的,而log4j在被slf4j调用的时候需要一个适配层。

reload4j:reload4j是Apache log4j版本1.x的一个分支,由于log4j存在一些安全漏洞,Apache社区和其他开发者开始寻求解决方案,reload4j就是其中之一。通过使用slf4j-reload4j,开发者可以在不修改太多代码的情况下,将他们的应用程序从log4j 1.x迁移到reload4j,从而提高应用程序的安全性和稳定性。

slf4j的主要搭配如下

  • Slf4j+logback slf4j-api.jar+logback-classic.jar+logback-core.jar
  • Slf4j+log4j slf4j-api.jar+slf4j-log4j12.jar+log4j.jar
  • Slf4j+jul slf4j-api.jar+slf4j-jdk14.jar
  • Slf4j无日志实现 slf4j-api.jar+slf4j-nop.jar

官网第二张图(桥接策略)
在这里插入图片描述
可以看到,上面含义是如果我们已经使用了其他日志框架的api,想转到另一种日志框架api,该如何使用桥接的jar包,如从logback到log4j,JUL到log4j等,本质是通过将一种框架日志交给slf4j,slf4j再通过桥接包到转给另一种框架日志输出,总的来说为以下情况:

  • 在使用JCL,则可以通过:jcl-over-slf4j.jar
  • 在使用log4j,则可以通过:log4j-over-slf4j.jar
  • 在使用JUL,则可通过jul-to-slf4j.jar
    在这里插入图片描述
    注意: 虽然使用 log4j-over-slf4j 可以实现 Log4j 桥接到 SLF4J,也可以使用 slf4j-log4j12 实现 SLF4J 适配到 Log4j,但是它不能同时使用它们,否则就会产生死循环。jcl 和 jul 也是同样的道理,jcl-over-slf4j.jar和slf4j-jcl.jar不能同时出现,jul-over-slf4j.jar和slf4j-log4j12.jar不能同时出现。

4.Logback

官网:https://logback.qos.ch/
Logback是由Ceki Gülcü(同时也是SLF4J的作者)创建的新一代日志框架,旨在解决Log4J的部分性能瓶颈和设计局限。Logback不仅实现了SLF4J API,还具有高度优化的性能、丰富的配置选项和强大的扩展能力。SpringBoot底层也是使用slf4j+logback的方式进行日志记录。
Logback主要分为三个模块:

  • logback-core :其它两个模块的基础模块
  • logback-classic :它是log4j的一个改良版本,同时它完整实现了slf4j API
  • logback-access :访问模块与Servlet容器集成提供通过Http来访问日志的功能

4.1 Logback 使用示例

1)添加依赖

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

实际开发中我们可以直接引入spring-boot-starter-web依赖,因为spring-boot-starter-web包含了spring-boot-starter 而spring-boot-starter包含了spring-boot-starter-logging

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
</dependency>

2)配置文件
logback会依次读取以下类型配置文件:

  1. logback.groovy
  2. logback-test.xml
  3. logback.xml
    如果均不存在会采用默认配置

logback-spring.yml

<?xml version="1.0" encoding="utf-8"?>
<!--配置文件说明:
共有一个父标签、两种属性、三个节点:
1.一个父标签:configuration
2. 两种属性:contextName和property
3. 三个节点:appender、root、logger

主要就是appender追加到哪里:控制台/文件,然后采用哪种pattern(在property定义了pattern格式)
然后就是logger和root配置,指定日志输出级别,以及引用哪种appender
-->
<configuration>
  <!--根节点<configuration>包含的属性:
  scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
  scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
  debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
  -->
  <contextName>logback-spring-demo-dev</contextName>
  <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg %n"/>
  <property name="pattern-color"
    value="%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%thread] %highlight(%-5level) %green(%logger{50}) - %highlight(%msg) %n"/>
  <!--文件路径输出说明,会自动生成文件夹及log文件,但是由于我这个是多模块,默认生成在父目录下的logs文件夹下面,所以要在子模块下生成要再加一个路径-->
  <property name="LOG_HOME" value="./springboot_log/logs"/>

  <!-- 控制台输出 -->
  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <!--ThresholdFilter为系统定义的拦截器,例如我们用ThresholdFilter来过滤掉ERROR级别以下的日志不输出到文件中。如果不用记得注释掉,不然你控制台会发现没日志~-->
    <!--<filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
    <!--<level>ERROR</level>-->
    <!--</filter>-->
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>${pattern}</pattern>
    </encoder>
  </appender>

  <!-- 控制台输出-带颜色 -->
  <appender name="CONSOLE-WITH-COLOR" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>${pattern-color}</pattern>
    </encoder>
  </appender>

  <!-- 文件输出 -->
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>${LOG_HOME}/%d.%i.log</fileNamePattern>
      <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
        <maxFileSize>10MB</maxFileSize>
      </timeBasedFileNamingAndTriggeringPolicy>
      <maxHistory>30</maxHistory>
    </rollingPolicy>

    <encoder>
      <pattern>${pattern}</pattern>
    </encoder>
  </appender>

  <!--相当于全局的配置-->
  <root level="INFO">
    <appender-ref ref="CONSOLE-WITH-COLOR"/>
    <appender-ref ref="FILE"/>
  </root>
  <!--1. root和logger是父子的关系。
  Logger的appender根据参数additivity决定是否要叠加root的appender,logger的级别是其自身定义的级别,和root的级别没什么关系。
  2. logger对单个包或类添加配置,相当于局部配置,root相当于全局配置
  如果logger里面配置了additivity="false",就会覆盖root的,只打印一遍;
  但是additivity="true",就会向上层再次传递,不会覆盖,而是打印两遍!
  -->

  <!--相当于局部配置:
  配置特定类/包使用不同的日志输出器appender:TestControoler2的会输出两遍,additivity="true"-->
  <logger name="com.apple.controller.TestController2" level="INFO" additivity="true">
    <appender-ref ref="CONSOLE"/>
  </logger>

</configuration>

3)测试

@Slf4j
@RestController
public class TestController {
    @RequestMapping("/index")
    public String index(){
        log.info("==========hello logback=============");
        return "hello logback";

    }
}

在这里插入图片描述

5.JCL(Jakarta Commons Logging)

官网:https://commons.apache.org/proper/commons-logging/
JCL是Apache基金会所属的项目,是一套Java日志接口,之前叫Jakarta Commons Logging,后更名为Commons Logging, 它本身并不提供日志的具体实现,(当然,commons-logging内部有一个SimpleLog但是功能非常常弱 ,所以一般不会单独使用它),而是在运行时绑定具体的日志组件来工作(如Log4j、JUL )。

JCL两个基本抽象类:

  • Log:日志记录器
  • LogFactory:日志工厂(负责创建Log实例)
    在这里插入图片描述

5.1 JCL例子

maven依赖:

<dependency> 
   <groupId>commons-logging</groupId> 
   <artifactId>commons-logging</artifactId>
   <version>1.2</version> 
</dependency>

测试

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class JCLTest {
    @Test
    public void testJCL(){
        // 创建日志对象
        Log log = LogFactory.getLog(JCLTest.class);
        // 记录debug级别的信息
        log.debug("This is debug message.");
        // 记录info级别的信息
        log.info("This is info message.");
        // 记录error级别的信息
        log.error("This is error message.");
    }
}

6.log4j2

官网:https://logging.apache.org/log4j/2.x/
Apache Log4J曾一度是Java世界中最流行的日志框架之一,以其灵活性和模块化设计著称。然而,随着时间推移,原版Log4J暴露出了一些性能和功能上的短板。于是,Apache基金会推出了Log4J2,这是一个经过彻底重构并优化的新版本,引入了许多新特性,主要有:

  • 异常处理,在 logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异 常处理机制。
  • 性能提升, log4j2相较于log4j 和logback都具有很明显的性能提升,后面会有官方测试的数据。
  • 自动重载配置,参考了 logback的设计,当然会提供自动刷新参数配置,最实用的就是我们在生产 上可以动态的修改日志的级别而不需要重启应用。
  • 无垃圾机制, log4j2在大部分情况下,都可以使用其设计的一套无垃圾机制,避免频繁的日志收集导致的jvm gc

6.1案例实现:

1)引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
    <version>2.6.13</version>
</dependency>

2) log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" monitorInterval="5">
    <properties>
        <property name="LOG_HOME">D:/logs</property>
    </properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n" />
        </Console>
        <File name="file" fileName="${LOG_HOME}/myfile.log">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l%c{36} - %m%n" />
        </File>
        <RandomAccessFile name="accessFile" fileName="${LOG_HOME}/myAcclog.log">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l%c{36} - %m%n" />
        </RandomAccessFile>
        <RollingFile name="rollingFile" fileName="${LOG_HOME}/myrollog.log"
                     filePattern="D:/logs/$${date:yyyy-MM-dd}/myrollog-%d{yyyyMM-dd-HH-mm}-%i.log">
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" />
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l%c{36} - %msg%n" />
            <Policies>
                <OnStartupTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="10 MB" />
                <TimeBasedTriggeringPolicy />
            </Policies>
            <DefaultRolloverStrategy max="30" />
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="trace">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

3)JAVA代码测试

import org.slf4j.LoggerFactory;

public class LogTest {
    static org.slf4j.Logger logger = LoggerFactory.getLogger(LogTest.class);
    public static void main(String[] args) {


        logger.trace("trace level");
        logger.debug("debug level");
        logger.info("info level");
        logger.warn("warn level");
        logger.error("error level");
    }
}

参考:

  1. http://t.csdnimg.cn/lW60J
  2. https://time.geekbang.org/column/article/220307
  3. https://www.cnblogs.com/cxyyh/p/10633581.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/618971.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业信息系统的总体框架

1.信息系统体系结构的总体参考框架 信息系统的架构&#xff08;Information System Architecture&#xff0c;ISA&#xff09;中的Architecture含义具有丰富内涵和作用&#xff0c;相比计算机领域的Architecture来说它的单一性、片面性模型是难以描述ISA的全部的&#xff0c;IS…

docker八大架构之单机架构

单机架构 什么是单机架构&#xff1f; 单机架构指的是应用服务和数据库服务公用同一台服务器。如下边两个图所示&#xff0c;当我们进行购物时&#xff0c;所有的物品信息和用户信息都是在同一个服务器下进行运行的&#xff0c;之所以称为单机架构就是因为它所有的操作是在同…

文心一言 VS 讯飞星火 VS chatgpt (257)-- 算法导论19.2 1题

一、给出图19-4(m)中的斐波那契堆调用 FIB-HEAP-EXTRACT-MIN 后得到的斐波那契堆。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 由于我不能直接画出图19-4(m)中的斐波那契堆&#xff0c;我将基于斐波那契堆的基本结构和操作FIB-HEAP-EXTRACT-MIN的一般行为来…

HTTPS对于网站到底价值几何?

现在HTTPS基本上已经是网站的标配了&#xff0c;很少会遇到单纯使用HTTP的网站。但是十年前这还是另一番景象&#xff0c;当时只有几家大型互联网公司的网站会使用HTTPS&#xff0c;大部分使用的都还是简单的HTTP&#xff0c;这一切是怎么发生的呢&#xff1f; 为什么要把网站…

根据蛋白质序列,计算其分子量(molecular weight),在线工具,原理和python代码

蛋白质分子量 蛋白质是由许多氨基酸残基通过肽键&#xff08;一个氨基酸的 α-羧基与另一个氨基酸的 α-氨基脱水缩合形成的化学键&#xff09;连接而成。蛋白质的分子量&#xff08;molecular weight&#xff09;为各个氨基酸的分子量之和&#xff0c;是蛋白质的重要理化参数…

速戳!高考生做近视手术须知,避免错过心仪大学

距离高考还有不到一个月的时间&#xff0c;考生们在紧张复习的同时&#xff0c;不要忘了了解意向专业、院校的视力要求。一些专业和院校录取不仅靠实力,还需要“视力”,考了个好成绩却因视力不达标而被专业、院校退档,这样的结果是我们不想看到的。如果你想圆军旅梦、警校梦、航…

面向对象设计(下)《Ⅱ》

文章目录 抽象类抽象类的理解&#xff08;抽象类不能实例化&#xff09; 设计模式模板方法设计模式代理模式工厂方法设计模式 接口接口的定义&#xff08;接口仅可以用public修饰&#xff09;接口的实现jdk1.8中接口的默认方法和静态方法 内部类成员内部类静态成员内部类的创建…

timerfd加epoll封装定时器

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1、用timerfd加epoll封装定时器的优点2、代码实现 1、用timerfd加epoll封装定时器的优点 定时器为什么需要timerfd 在设计定时器时&#xff0c;我们首先想到的就是…

HNU-操作系统OS-2024期中考试

前言 该卷为22计科/智能OS期中考卷。 感谢智能22毕宿同学记忆了考卷考题。 同学评价&#xff1a;总体简单&#xff1b;第1&#xff0c;7概念题较难需要看书&#xff1b;第4&#xff0c;5题原题。 欢迎同学分享答案。 【1】共10分 操作系统的设计目标有哪些&#xff1f; 【…

Attention-guided Feature Distillation for Semantic Segmentation

摘要 与现有的复杂方法相比&#xff0c;该方法通常用于从老师那里提取知识给学生&#xff0c;该方法展示了一种简单而强大的方法&#xff0c;可以利用精细的特征映射来转移注意力。事实证明&#xff0c;该方法在提取丰富信息方面是有效的&#xff0c;在作为密集预测任务的语义…

springfox.documentation.spi.DocumentationType没有OAS_30(从swagger2转到swagger3出现的问题)

直接开讲&#xff1a; 查看源码根本没有OAS_30的类型选择 右键package的springfox找到maven下载的包&#xff0c;打开到资源管理器 可以看到项目优先使用2版本的jar包&#xff0c;但是OAS_30只在3版本中才有&#xff0c;意思就是让项目优先使用以下图片中的3.0.0jar包 解决办法…

智能文件夹改名助手:一键秒级恢复原始名称,轻松告别繁琐操作,提升文件管理效率

文件夹管理成为了我们日常工作和生活中不可或缺的一部分。然而&#xff0c;随着文件数量的不断增加和文件夹命名的复杂性&#xff0c;我们经常面临着重命名文件夹的繁琐操作。你是否曾经因为误改文件夹名称而头疼不已&#xff1f;是否曾经为了找回原始名称而耗费大量时间&#…

docker容器实现https访问

前言&#xff1a; 【云原生】docker容器实现https访问_docker ssl访问-CSDN博客 一术语介绍 ①key 私钥 明文--自己生成&#xff08;genrsa &#xff09; ②csr 公钥 由私钥生成 ③crt 证书 公钥 签名&#xff08;自签名或者由CA签名&#xff09; ④证书&#xf…

【Java】:向上转型、向下转型和ClassCastException异常

目录 先用一个生动形象的例子来解释向上转型和向下转型 向上转型&#xff08;Upcasting&#xff09; 向下转型&#xff08;Downcasting&#xff09; 向上转型 概念 例子 发生向上转型的情况 1.子类对象赋值给父类引用 2.方法参数传递 3.返回值 向下转型 概念 注意…

SpringSecurity的核心原理使用总结

1. SpringSecurity的核心原理 对于最原始Servlet请求处理的层次结构 客户端->过滤器链->Servlet 对于在SpringMVC中处理请求的层次结构 如何让Filter与Spring建立连接呢? 因此它增加了一个DelegatingFilterProxy 它是SpringMVC提供的的Filter,它内部代理了一个原生的F…

代码随想录——二叉树的层序遍历(Leetcode102)二叉树层序遍历的模板

题目链接 层序遍历&#xff08;队列&#xff09; 层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。 需要借用一个辅助数据结构即队列来实现&#xff0c;队列先进先出&#xff0c;符合一层一层遍历的逻辑&#xff0c;而用…

java项目之企业OA管理系统源码(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的企业OA管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 企业OA管理系统的主要使用…

搭建Springboot的基础开发框架-02

本系列专题虽然是按教学的深度来定稿的&#xff0c;但在项目结构和代码组织方面是按公司系统的要求来书定的。在本章中主要介绍下基础开发框架的功能。后续所有章节的项目全是在本基础框架的基础上演进的。 工程结构介绍 SpringbootSeries&#xff1a;父工程&#xff0c;定义一…

语言:C#

一、VSCode生成exe 二、

【计算机毕业设计】基于微信小程序校园服务平台

随着 计算机技术的成熟&#xff0c;互联网的建立&#xff0c;如今&#xff0c;PC平台上有许多关于校园服务方面的应用程序&#xff0c;但由于使用时间和地点上的限制&#xff0c;用户在使用上存在着种种不方便&#xff0c;而开发一款基于微信小程序的校园服务平台&#xff0c;能…