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 {@Testpublic 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 {@Testpublic 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也能生效。

@Testpublic 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.LogManagerSystem.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 {@Testpublic 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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA 集合(单列集合)

集合框架 1.集合的特点 a.只能存储引用数据类型的数据 b.长度可变 c.集合中有大量的方法,方便我们操作 2.分类: a.单列集合:一个元素就一个组成部分: list.add(“张三”) b.双列集合:一个元素有两部分构成: key 和 value map.put(“涛哥”,“金莲”) -> key,value叫做键值…

锁和MVCC如何实现mysql的隔离级别

概述 MVCC解决读的隔离性&#xff0c;加锁解决写的隔离性。 读未提交 读未提交&#xff0c;更新数据大概率使用的是独享锁吧。 读已提交 在 Read Committed&#xff08;读已提交&#xff09;隔离级别下&#xff0c;每次执行读操作时都会生成一个新的 read view。这是因为在读…

AI 图像生成-环境配置

一、python环境安装 Windows安装Python&#xff08;图解&#xff09; 二、CUDA安装 CUDA安装教程&#xff08;超详细&#xff09;-CSDN博客 三、Git安装 git安装教程&#xff08;详细版本&#xff09;-CSDN博客 四、启动器安装 这里安装的是秋叶aaaki的安装包 【AI绘画…

【GlobalMapper精品教程】081:WGS84/CGCS2000转Lambert投影

参考阅读:ArcGIS实验教程——实验十:矢量数据投影变换 文章目录 一、加载实验数据二、设置输出坐标系三、数据导出一、加载实验数据 打开配套案例数据包中的data081.rar中的矢量数据,如下所示: 查看源坐标系:双击图层的,图层投影选项卡,数据的已有坐标系为WGS84地理坐标…

【3dmax笔记】021:对齐工具(快速对齐、法线对齐、对齐摄影机)

文章目录 一、对齐二、快速对齐三、法线对齐四、对齐摄影机五、注意事项3dmax提供了对齐、快速对齐、法线对齐和对齐摄像机等对齐工具: 对齐工具选项: 下面进行一一讲解。 一、对齐 快捷键为Alt+A,将当前选择对象与目标对象进行对齐。 最大对最大:

【小笔记】neo4j用load csv指令导入数据

【小笔记】neo4j用load csv指令导入数据 背景 很久没有用load CSV的方式导入过数据了因为它每次导入有数量限制&#xff08;印象中是1K还是1W&#xff09;&#xff0c;在企业中构建的图谱往往都是大规模的&#xff0c;此时通常采用的是Neo4j-admin import方式。最近遇到了一些…

振弦式表面应变计怎么安装

振弦式表面应变计是一种用于测量结构表面应变的高精度传感器&#xff0c;广泛应用于工程和科研领域。正确安装振弦式表面应变计对于确保测量结果的准确性至关重要。以下是安装振弦式表面应变计的步骤和注意事项&#xff1a; 1. 准备工作 在开始安装前&#xff0c;需要准备以下工…

whisper之初步使用记录

文章目录 前言 一、whisper是什么&#xff1f; 二、使用步骤 1.安装 2.python调用 3.识别效果评估 4.一点封装 5.参考链接 总结 前言 随着AI大模型的不断发展&#xff0c;语音识别等周边内容也再次引发关注&#xff0c;通过语音转文字再与大模型交互&#xff0c;从而…

【Gitlab远程访问本地仓库】Gitlab如何安装配置并结合内网穿透实现远程访问本地仓库进行管理

文章目录 前言1. 下载Gitlab2. 安装Gitlab3. 启动Gitlab4. 安装cpolar5. 创建隧道配置访问地址6. 固定GitLab访问地址6.1 保留二级子域名6.2 配置二级子域名 7. 测试访问二级子域名 前言 GitLab 是一个用于仓库管理系统的开源项目&#xff0c;使用Git作为代码管理工具&#xf…

为什么质量工程师必学六西格玛?突破职业发展的瓶颈?

在质量管理领域工作多年&#xff0c;你是否曾感受到事业发展的停滞不前&#xff1f;3年、5年的职业生涯&#xff0c;薪水依旧停留在每月5000-7000&#xff0c;而同行业的其他人却能月入2-3万&#xff0c;这种差距让人不禁陷入深思。 问题究竟出在哪里&#xff1f;为什么我们的…

揭秘图形编程 动静接口如何助力 AGV 集成

在公司软件开发团队的办公室里&#xff0c;阳光透过窗户洒在排列整齐的办公桌上。卧龙坐在办公桌前&#xff0c;面前摊开一份内测报告&#xff0c;他的手指时不时地敲击着桌面&#xff0c;流露出内心的烦躁。他抬起头&#xff0c;眼神中透露出一丝困惑&#xff0c;看向正在文件…

【网络安全】【Frida实践案例】某图xx付费功能逆向分析(一)

文章目录 一、目标应用二、环境三、步骤1、查看布局id2、用到的Log日志类信息3、尝试hook VIP判断方法 四、总结五、相关源码 1、文章仅供学习参考&#xff0c;严禁非法使用&#xff01;如非法使用&#xff0c;而导致的一切后果&#xff0c;由使用者自负&#xff01; 2、禁止将…

【C++】string类常用函数用法总结

目录 常用函数一览 默认成员函数 与容量有关的函数 part 1 part 2 part 3 与访问和遍历有关的函数 与修改有关的函数 npos 与string相关的其它常用函数 常用非成员函数 getline和cin的区别 常用函数一览 //默认成员函数 string();string(const char* s);string(si…

docker八大架构之应用服务集群架构

应用服务集群架构 在之前&#xff0c;一个应用层要负责所有的用户操作&#xff0c;但是有时用户增加后就会导致供不应求的现象&#xff08;单个应用不足以支持海量的并发请求&#xff0c;高并发的时候站点响应变慢&#xff09;&#xff0c;这时就需要增加应用层服务器&#xf…

【STM32 |GPIO】GPIO结构、GPIO输出

目录 GPIO简介 GPIO的基本结构 GPIO位结构&#xff08;每一位的具体电路结构&#xff09; 输入 上拉和下拉电阻 斯密特触发器 ​编辑 输出 GPIO模式 ​编辑 浮空输入、上拉输入、下拉输入 模拟输入 开漏输出和推挽输出 复用开漏输出和复用推挽输出 LED和蜂鸣器…

【资源分享】完胜谷歌翻译的Deepl翻译

::: block-1 “时问桫椤”是一个致力于为本科生到研究生教育阶段提供帮助的不太正式的公众号。我们旨在在大家感到困惑、痛苦或面临困难时伸出援手。通过总结广大研究生的经验&#xff0c;帮助大家尽早适应研究生生活&#xff0c;尽快了解科研的本质。祝一切顺利&#xff01;—…

【数据结构与算法】力扣 111. 二叉树的最小深度

题目描述 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明&#xff1a; 叶子节点是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a; root [3,9,20,null,null,15,7] 输出&#xff1a; 2示例 2&#…

长事务的理解和预防

我们常常听说数据库发生了“长事务”而导致很严重的后果。那么何为长事务&#xff1f;长事务是如何产生的&#xff1f;长事务对数据库有什么影响&#xff1f;如何防止长事务的产生&#xff1f;以下对这几方面进行阐述和说明&#xff0c;以加深对SinoDB长事务的理解。 1&#x…

Python-VBA函数之旅-super函数

目录 一、super函数的常见应用场景 二、super函数使用注意事项 三、如何用好super函数&#xff1f; 1、super函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a; https://myelsa1024.blog.csdn.net/ 一、su…

AI代理和AgentOps生态系统的剖析

1、AI代理的构成&#xff1a;AI代理能够根据用户的一般性指令自行做出决策和采取行动。 主要包含四个部分&#xff1a; &#xff08;1&#xff09;大模型&#xff08;LLM&#xff09; &#xff08;2&#xff09;工具&#xff1a;如网络搜索、代码执行等 &#xff08;3&#x…