全面梳理Spring Boot框架的日志体系结构

news2025/1/16 8:50:53

文章目录

    • 1. Java 日志概览
      • 1.1 总体概览
      • 1.2 日志级别
      • 1.3 综合对比
      • 1.4 最佳实践
    • 2. Spring Boot 日志实现
      • 2.1 Spring Boot 日志配置
      • 2.2 Logback 配置
      • 2.3 Log4j 配置

之前录过一个视频和大家分享 Spring Boot 日志问题,但是总感觉差点意思,因此松哥打算再通过一篇文章来和大家捋一捋 Java 中的日志问题,顺便我们把 Spring Boot 中的日志问题也说清楚。

1. Java 日志概览

说到 Java 日志,很多初学者可能都比较懵,因为这里涉及到太多东西了:Apache Commons LoggingSlf4jLog4jLog4j2LogbackJava Util Logging 等等,这些框架各自有什么作用?他们之间有什么区别?

1.1 总体概览

下面这张图很好的展示了 Java 中的日志体系:

可以看到,Java 中的日志框架主要分为两大类:日志门面日志实现

日志门面

日志门面定义了一组日志的接口规范,它并不提供底层具体的实现逻辑。Apache Commons LoggingSlf4j 就属于这一类。

日志实现

日志实现则是日志具体的实现,包括日志级别控制、日志打印格式、日志输出形式(输出到数据库、输出到文件、输出到控制台等)。Log4jLog4j2Logback 以及 Java Util Logging 则属于这一类。

将日志门面和日志实现分离其实是一种典型的门面模式,这种方式可以让具体业务在不同的日志实现框架之间自由切换,而不需要改动任何代码,开发者只需要掌握日志门面的 API 即可。

日志门面是不能单独使用的,它必须和一种具体的日志实现框架相结合使用。

那么日志框架是否可以单独使用呢?

技术上来说当然没问题,但是我们一般不会这样做,因为这样做可维护性很差,而且后期扩展不易。例如 A 开发了一个工具包使用 Log4j 打印日志,B 引用了这个工具包,但是 B 喜欢使用 Logback 打印日志,此时就会出现一个业务使用两个甚至多个日志框架,开发者也需要维护多个日志的配置文件。因此我们都是用日志门面打印日志。

1.2 日志级别

使用日志级别的好处在于,调整级别,就可以屏蔽掉很多调试相关的日志输出。不同的日志实现定义的日志级别不太一样,不过也都大同小异。

Java Util Logging

Java Util Logging 定义了 7 个日志级别,从严重到普通依次是:

  • SEVERE
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST

因为默认级别是 INFO,因此 INFO 级别以下的日志,不会被打印出来。

Log4j

Log4j 定义了 8 个日志级别(除去 OFF 和 ALL,可以说分为 6 个级别),从严重到普通依次是:

  • OFF:最高等级的,用于关闭所有日志记录。
  • FATAL:重大错误,这种级别可以直接停止程序了。
  • ERROR:打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。
  • WARN:警告提示。
  • INFO:用于生产环境中输出程序运行的一些重要信息,不能滥用。
  • DEBUG:用于开发过程中打印一些运行信息。
  • TRACE
  • ALL 最低等级的,用于打开所有日志记录。

Logback

Logback 日志级别比较简单,从严重到普通依次是:

  • ERROR
  • WARN
  • INFO
  • DEBUG
  • TRACE

1.3 综合对比

Java Util Logging 系统在 JVM 启动时读取配置文件并完成初始化,一旦应用程序开始运行,就无法修改配置。另外,这种日志实现配置也不太方便,只能在 JVM 启动时传递参数,像下面这样:

-Djava.util.logging.config.file=<config-file-name>。

由于这些局限性,导致 Java Util Logging 并未广泛使用。

Log4j 虽然配置繁琐,但是一旦配置完成,使用起来就非常方便,只需要将相关的配置文件放到 classpath 下即可。在很多情况下,Log4j 的配置文件我们可以在不同的项目中反复使用。

Log4j 可以和 Apache Commons Logging 搭配使用,Apache Commons Logging 会自动搜索并使用 Log4j,如果没有找到 Log4j,再使用 Java Util Logging

Log4j + Apache Commons Logging 组合更得人心的是 Slf4j + Logback 组合。

LogbackSlf4j 的原生实现框架,它也出自 Log4j 作者(Ceki Gülcü)之手,但是相比 Log4j,它拥有更多的优点、特性以及更强的性能。

1.4 最佳实践

  • 如果不想添加任何依赖,使用 Java Util Logging 或框架容器已经提供的日志接口。
  • 如果比较在意性能,推荐:Slf4j + Logback
  • 如果项目中已经使用了 Log4j 且没有发现性能问题,推荐组合为:Slf4j + Log4j2

2. Spring Boot 日志实现

Spring Boot 使用 Apache Commons Logging 作为内部的日志框架门面,它只是一个日志接口,在实际应用中需要为该接口来指定相应的日志实现。

Spring Boot 默认的日志实现是 Logback。这个很好查看:随便启动一个 Spring Boot 项目,从控制台找一行日志,例如下面这样:

img

考虑到最后的 prod 是一个可以变化的字符,我们在项目中全局搜索:The following profiles are active,结果如下:

img

在日志输出的那一行 debug。然后再次启动项目,如下图:

img

此时我们就可以看到真正的日志实现是 Logback

其他的诸如 Java Util LoggingLog4j 等框架,Spring Boot 也有很好的支持。

在 Spring Boot 项目中,只要添加了如下 web 依赖,日志依赖就自动添加进来了:

<dependency>



    <groupId>org.springframework.boot</groupId>



    <artifactId>spring-boot-starter-web</artifactId>



</dependency>

2.1 Spring Boot 日志配置

Spring Boot 的日志系统会自动根据 classpath 下的内容选择合适的日志配置,在这个过程中首选 Logback。

如果开发者需要修改日志级别,只需要在 application.properties 文件中通过 logging.level 前缀+包名 的形式进行配置即可,例如下面这样:

logging.level.org.springframework.web=debug



logging.level.org.hibernate=error

如果你想将日志输出到文件,可以通过如下配置指定日志文件名:

logging.file.name=javaboy.log

logging.file.name 可以只指定日志文件名,也可以指定日志文件全路径,例如下面这样:

logging.file.name=/Users/sang/Documents/javaboy/javaboy.log

如果你只是想重新定义输出日志文件的路径,也可以使用 logging.file.path 属性,如下:

logging.file.path=/Users/sang/Documents/javaboy

如果想对输出到文件中的日志进行精细化管理,还有如下一些属性可以配置:

  • logging.logback.rollingpolicy.file-name-pattern:日志归档的文件名,日志文件达到一定大小之后,自动进行压缩归档。
  • logging.logback.rollingpolicy.clean-history-on-start:是否在应用启动时进行归档管理。
  • logging.logback.rollingpolicy.max-file-size:日志文件大小上限,达到该上限后,会自动压缩。
  • logging.logback.rollingpolicy.total-size-cap:日志文件被删除之前,可以容纳的最大大小。
  • logging.logback.rollingpolicy.max-history:日志文件保存的天数。

日志文件归档这块,小伙伴们感兴趣可以自己试下,可以首先将 max-file-size 属性调小,这样方便看到效果:

logging.logback.rollingpolicy.max-file-size=1MB

然后添加如下接口:

@RestController



public class HelloController {



    private static final Logger logger = getLogger(HelloController.class);



    @GetMapping("/hello")



    public void hello() {



        for (int i = 0; i < 100000; i++) {



            logger.info("hello javaboy");



        }



    }



}

访问该接口,可以看到最终生成的日志文件被自动压缩了:

img

application.properties 中还可以配置日志分组。

日志分组能够把相关的 logger 放到一个组统一管理。

例如我们可以定义一个 tomcat 组:

logging.group.tomcat=org.apache.catalina,org.apache.coyote, org.apache.tomcat

然后统一管理 tomcat 组中的所有 logger:

logging.level.tomcat=TRACE

Spring Boot 中还预定义了两个日志分组 web 和 sql,如下:

img

不过在 application.properties 中只能实现对日志一些非常简单的配置,如果想实现更加细粒度的日志配置,那就需要使用日志实现的原生配置,例如 Logbackclasspath:logback.xmlLog4jclasspath:log4j.xml 等。如果这些日志配置文件存在于 classpath 下,那么默认情况下,Spring Boot 就会自动加载这些配置文件。

2.2 Logback 配置

2.2.1 基本配置

默认的 Logback 配置文件名有两种:

  • logback.xml:这种配置文件会直接被日志框架加载。
  • logback-spring.xml:这种配置文件不会被日志框架直接加载,而是由 Spring Boot 去解析日志配置,可以使用 Spring Boot 的高级 Profile 功能。

Spring Boot 中为 Logback 提供了四个默认的配置文件,位置在 org/springframework/boot/logging/logback/,分别是:

  • defaults.xml:提供了公共的日志配置,日志输出规则等。
  • console-appender.xml:使用 CONSOLE_LOG_PATTERN 添加一个ConsoleAppender。
  • file-appender.xml:添加一个 RollingFileAppender。
  • base.xml:为了兼容旧版 Spring Boot 而提供的。

如果需要自定义 logback.xml 文件,可以在自定义时使用这些默认的配置文件,也可以不使用。一个典型的 logback.xml 文件如下(resources/logback.xml):

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



<configuration>



    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>



    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />



    <root level="INFO">



        <appender-ref ref="CONSOLE" />



    </root>



    <logger name="org.springframework.web" level="DEBUG"/>



</configuration>

可以通过 include 引入 Spring Boot 已经提供的配置文件,也可以自定义。

2.2.2 输出到文件

如果想禁止控制台的日志输出,转而将日志内容输出到一个文件,我们可以自定义一个 logback-spring.xml 文件,并引入前面所说的 file-appender.xml 文件。

像下面这样(resources/logback-spring.xml):

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



<configuration>



    <include resource="org/springframework/boot/logging/logback/defaults.xml" />



    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>



    <include resource="org/springframework/boot/logging/logback/file-appender.xml" />



    <root level="INFO">



        <appender-ref ref="FILE" />



    </root>



</configuration>

2.3 Log4j 配置

如果 classpath 下存在 Log4j2 的依赖,Spring Boot 会自动进行配置。

默认情况下 classpath 下当然不存在 Log4j2 的依赖,如果想使用 Log4j2,可以排除已有的 Logback,然后再引入 Log4j2,如下:

<dependency>



    <groupId>org.springframework.boot</groupId>



    <artifactId>spring-boot-starter-web</artifactId>



    <exclusions>



        <exclusion>



            <groupId>org.springframework.boot</groupId>



            <artifactId>spring-boot-starter-logging</artifactId>



        </exclusion>



    </exclusions>



</dependency>



<dependency>



    <groupId>org.springframework.boot</groupId>



    <artifactId>spring-boot-starter-log4j2</artifactId>



</dependency>

Log4j2 的配置就比较容易了,在 reources 目录下新建 log4j2.xml 文件,内容如下:

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



<configuration status="warn">



    <properties>



        <Property name="app_name">logging</Property>



        <Property name="log_path">logs/${app_name}</Property>



    </properties>



    <appenders>



        <console name="Console" target="SYSTEM_OUT">



            <PatternLayout pattern="[%d][%t][%p][%l] %m%n" />



        </console>



        <RollingFile name="RollingFileInfo" fileName="${log_path}/info.log"



                     filePattern="${log_path}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz">



            <Filters>



                <ThresholdFilter level="INFO" />



                <ThresholdFilter level="WARN" onMatch="DENY"



                                 onMismatch="NEUTRAL" />



            </Filters>



            <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />



            <Policies>



                <TimeBasedTriggeringPolicy interval="1" modulate="true" />



                <SizeBasedTriggeringPolicy size="2 MB" />



            </Policies>



            <DefaultRolloverStrategy compressionLevel="0" max="10"/>



        </RollingFile>



        <RollingFile name="RollingFileWarn" fileName="${log_path}/warn.log"



                     filePattern="${log_path}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz">



            <Filters>



                <ThresholdFilter level="WARN" />



                <ThresholdFilter level="ERROR" onMatch="DENY"



                                 onMismatch="NEUTRAL" />



            </Filters>



            <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />



            <Policies>



                <TimeBasedTriggeringPolicy interval="1" modulate="true" />



                <SizeBasedTriggeringPolicy size="2 MB" />



            </Policies>



            <DefaultRolloverStrategy compressionLevel="0" max="10"/>



        </RollingFile>



 



        <RollingFile name="RollingFileError" fileName="${log_path}/error.log"



                     filePattern="${log_path}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz">



            <ThresholdFilter level="ERROR" />



            <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />



            <Policies>



                <TimeBasedTriggeringPolicy interval="1" modulate="true" />



                <SizeBasedTriggeringPolicy size="2 MB" />



            </Policies>



            <DefaultRolloverStrategy compressionLevel="0" max="10"/>



        </RollingFile>



    </appenders>



    <loggers>



        <root level="info">



            <appender-ref ref="Console" />



            <appender-ref ref="RollingFileInfo" />



            <appender-ref ref="RollingFileWarn" />



            <appender-ref ref="RollingFileError" />



        </root>



    </loggers>



</configuration>

首先在 properties 节点中指定了应用名称以及日志文件位置。

然后通过几个不同的 RollingFile 对不同级别的日志分别处理,不同级别的日志将输出到不同的文件,并按照各自的命名方式进行压缩。

这段配置比较程式化,小伙伴们可以保存下来做成 IntelliJ IDEA 模版以便日常使用。

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

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

相关文章

第十八章 SPFA算法以及负环问题(利用dijkstra推导出该算法,超级详细!!)

第十八章 SPFA算法以及负环问题一、dijkstra算法的弊端二、dijkstra算法的优化1、SPFA算法&#xff08;1&#xff09;算法思路&#xff1a;&#xff08;2&#xff09;算法模板&#xff1a;问题&#xff1a;模板&#xff1a;逐行分析&#xff1a;三、SFPA解决负环问题&#xff1…

uni-clould常用笔记

一&#xff0c;云函数 定义&#xff1a; // hellocf云函数index.js入口文件代码 use strict; exports.main async (event, context) > {//event为客户端上传的参数let c event.a event.breturn {sum: c} // 通过return返回结果给客户端 }调用&#xff1a; // 客户端调…

【Linux】su 和 sudo 命令

su 命令 su 命令作用&#xff1a;在已登录的会话中切换到另外一个用户。 1、su root 切换超级用户root角色&#xff0c;但不切换用户环境。需要输入root角色的密码。 2、su - root 切换root角色&#xff0c;并切换用户环境。 sudo 命令 sudo 命令作用&#xff1a;暂时切…

【树莓派不吃灰】命令篇⑩ 记录Linux常用命令

目录1. 命令格式1.1 mount2. 文件处理命令2.1 ls2.2 mkdir2.3 cd2.4 pwd2.5 rmdir2.6 cp2.7 mv2.8 rm2.9 touch2.10 cat、tac2.11 more、less、head、tail2.12 ln3. 权限管理命令3.1 chmod3.2 chown3.3 chgrp3.4 umask4. 文件搜索命令4.1 find4.2 locate4.3 which4.4 whereis4.…

进阶 - Git的标签管理

本篇文章&#xff0c;是基于我自用Windows&#xff08;Win10&#xff09;系统当做示例演示 本地仓库在&#xff1a;E:\test_git_rep 远程仓库是&#xff1a;gitgithub.com:lili40342/test_git_rep.git 描述测试环境的目的&#xff0c;是更好的解释测试过程&#xff0c;以免对你…

elasticsearch-8.5.2快速入门和kibana-8.5.2的使用

一、 安装 官方安装Elasticsearch&#xff0c;和ES可视化工具kibana。安装下载过程略。 二、 启动Elasticsearch。 windows系统&#xff0c;直接进入到如图目录&#xff0c;然后启动elasticsearch.bat&#xff0c;这个就是ES服务。 启动后&#xff0c;我们可以访问https://…

#438 沸腾客厅:从数字藏品到Web3.0,不止于事件营销

点击文末“阅读原文”即可收听本期节目数字藏品是什么&#xff1f;数字藏品是指使用区块链技术&#xff0c;对应特定的作品、艺术品生成的唯一数字凭证&#xff0c;在保护其数字版权的基础上&#xff0c;实现真实可信的数字化发行、购买、收藏和使用。2022年是天津文化中心成立…

「Redis」10 三大缓存问题、分布式锁

笔记整理自【尚硅谷】Redis 6 入门到精通 超详细 教程 Redis——三大缓存问题、分布式锁 1. 三大缓存 缓存穿透 问题描述 key 对应的数据在数据源并不存在&#xff0c;每次针对此 key 的请求从缓存获取不到&#xff0c;请求都会压到数据源&#xff0c;从而可能压垮数据源。 …

Java入门教程(27)——重写和final关键字

文章目录1.重写(override)2.final关键字实例1&#xff1a;修饰变量实例2.修饰方法实例3.修饰类1.重写(override) 什么是重写呢&#xff0c;顾名思义&#xff0c;子类重写父类的方法&#xff0c;可以用自身行为替换父类行为。方法重写需要符合的条件&#xff1a; 方法名、形参列…

【Linux】静动态库的制作和使用

前言 好久不见&#xff0c;甚是想念~ 本篇文章具体以操作为主&#xff0c;介绍在Linux下如何打包动静态库&#xff0c;并且如何使用这些库&#xff0c;同时&#xff0c;简单的阐述一下原理。让我们开始吧~ 上一篇Linux文章传送地址~ 【Linux】基础IO的理解与操作 - fd_柒海啦的…

复合材料专场 | ABAQUS车载四型复合材料气瓶固化过程的数值模拟分析攻略

复合材料气瓶固化的热场本质上可以认为包含两个阶段&#xff0c;复合材料气瓶表面和周围通过与空气的热对流换热&#xff0c;复合材料与内部塑料芯模以及金属接头的传热。在第一个阶段整体温度较低&#xff0c;热量从表面向复合材料层内部流入&#xff0c;此时固化速率很低&…

Python使用Opencv图像处理方法完成手势识别(三)tkinter制作GUI界面

前面对手势识别已经差不多完成。 这一章来制作一个手势识别GUI界面和说一下精确度不够问题所在。 首先是精确度不够的问题&#xff1a; 让手势更规范&#xff0c;手掌张开点。首先应该调节Hsv阈值&#xff0c;因为手掌和环境颜色与我的可能有差异。调整面积&#xff0c;周长阈…

ADI Blackfin DSP处理器-BF533的开发详解7:SPI接口的驱动和应用(含源代码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 接口功能介绍 SPI 接口是 4 线串口&#xff0c;可以连接 SPIFLASH&#xff0c;SPI 接口的 AD&#xff0c;DA 等等。ADSP-BF533 的 SPI 接口支持主…

【Python合集系列】爬虫有什么用,网友纷纷给出自己的答案,王老师,我..我想学那个..爬虫。可以嘛?“(代码免费分享)

导语 Hello&#xff0c;大家好呀&#xff01;我是木木子吖&#xff5e; 一个集美貌幽默风趣善良可爱并努力码代码的程序媛一枚。 听说关注我的人会一夜暴富发大财哦~ &#xff08;哇哇哇 这真的爱&#x1f60d;&#x1f60d;&#xff09; 生活中总有些东西值得爬一爬 爬虫…

Java 内存模型之 JMM

—— 计算机存储结构 计算机存储结构&#xff0c;从本地磁盘到主存到 CPU 缓存&#xff0c;也就是硬盘到内存&#xff0c;到CPU&#xff0c;一般对应的程序的操作就是从数据库到内存然后到CPU进行计算CPU拥有多级缓存&#xff0c;&#xff08;CPU和物理主内存的速度不一致&…

群集搭建【LNMP+负载均衡+高可用+跳板机】

目录 项目需求 LNMP部署 web1部署 mysql部署 php部署 nfs部署 LNMP测试 负载均衡与高可用 web2部署 lb1部署 lb2部署 验证群集 跳板机功能 测试跳板机 项目需求 实验目标&#xff1a;根据拓扑图搭建环境&#xff0c;安装论坛&#xff0c;创建证书通过https访问&#xff0c;实现…

一文搞懂 Nginx

文章目录一、前言二、NGINX 指令与上下文2.1 指令2.2 上下文三、NGINX 静态文件处理3.1 静态文件配置3.2 静态文件类型处理四、NGINX 动态路由4.1 Location 匹配4.1.1 前缀匹配4.1.2 精准匹配4.1.3 正则匹配4.1.4 优先前缀匹配4.2 Location 匹配优先级4.2.1 匹配优先级对比4.2.…

学好selenium工具,能实现你想得到的所有事情

文章目录一、介绍背景二、开发与实现2.1、部署开发环境2.2、开始码代码<demo只为提供思路>2.3、思路分析2.4、难点解析三、总结一、介绍背景 情况是这样的&#xff1a;某段时间之前&#xff0c;开发想找我用ui自动化帮他们实现一个功能&#xff1a;在系统某些时候生成报告…

[附源码]计算机毕业设计大学生心理健康测评系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

零基础CSS入门教程(17)——内边距

本章目录1.任务目标2.默认情况3.有内边距4.小结1.任务目标 上一篇介绍了外边距&#xff0c;也就是元素跟相邻元素的距离。 本篇来介绍内边距&#xff0c;顾名思义&#xff0c;内边距是指的元素内部的内容&#xff0c;与元素的边的距离 2.默认情况 <!DOCTYPE html> <…