springboot日志使用入门
★ 典型的Spring Boot日志依赖:
spring-boot-start.jar
-- spring-boot-starter-logging.jar (Spring Boot的日志包)
-- logback(core、classic)
-- log4j-to-slf4j.jar
-- jul-to-slf4j.jar
就是springboot的默认的日志依赖实现。创建项目的时候存在这个依赖里面。
★ Java领域的日志框架可分为:
▲ 门面类(抽象层):SLF4J、JCL(Apache ***mons logging)、JBoss Logging
▲ 日志实现:Log4j、Log4j2、Logback、JUL(JDK内置的java.util.logging)
推荐应用程序面向日志门面编程,以便底层可以在不同的日志实现之间自由切换。
项目中的日志框架,通常是两个:日志门面(抽象)+ 日志实现
★ Spring Boot的日志设计
下面的日志实现就是基于 SLF4J+Logback
SLF4J+Logback:SLF4J是门面,Logback是实现
▲ Spring Boot日志采用如下组合:
- SLF4J+Logback:SLF4J是门面,Logback是实现
▲ 由于Spring Boot要整合大量其他框架,这些框架底层可能采用了各种不同的日志实现,
因此Spring Boot需要将这些日志全部“路由”给SLF4J(把所有日志统一交给SLF4J来输出),
以后开发者就只需要设置SLF4J的日志即可。
因此还需要
- log4j-to-slf4j.jar:它负责将Log4j日志路由到SLF4J。
- jul-to-slf4j.jar:负责将JUL日志路由到SLF4J。
【说明】:当你项目用了Spring Boot之后,Spring boot会负责将所有第三方框架日志都路由给SLF4J,
开发者就只需要配置SLF4J日志,即可对所有的日志进行全盘控制。
【注意】:将Spring Boot应用部署到服务器上,JUL生成的日志将不再路由到Spring Boot应用的日志。
——由于应用服务器底层往往都使用JUL日志,由于应用服务器本身、及服务器上可能部署了其他应用的日志
这些日志当然与我们Spring Boot应用无关,所以Spring Boot默认不会将这些日志路由到SLF4J上。
【总结】 Spring Boot统一了Java领域的所有框架所可能用到的日志实现,并将这些日志全部“路由”给SLF4J来管理,
因此开发者只要管理SLF4J日志,即可对项目中所有日志框架进行管理。
★ 使用日志:
(1)在程序中获取Logger对象(org.slf4j包下的),通过LoggerFactory。
也可用Lombok的@Slf4j注解来获取。
(2)在要输出日志的地方(相当于以前Systme.out.println)
Logger的trace\debug\info\warn\error来输出不同级别的日志。
★ 日志级别
▲ 日志级别:
TRACE < DEBUG < INFO < WARNING < ERROR
▲ 当日志输出方法的级别高于或等于应用日志的设置级别时,该日志才会实际输出。
Spring Boot应用默认的日志级别是INFO,因此它默认只输出info、warn、error方法输出的日志。
★ 设置日志级别:
设置日志的级别,可通过以下方式:
▲ 改变Spring Boot的核心日志级别
通过debug=true或trace=true等属性(通过配置文件、命令行参数、系统变量、OS环境变量等方式)
改变整个Spring Boot核心的日志级别。
▲ 改变程序组件(包括所有各种框架)的核心日志级别
通过logging.level.<logger-name>=<level>属性(可通过配置文件、命令行参数、系统变量等方式)设置指定日志的日志级别。
其中<logger-name>代表日志名,通常就是包名或全限定的类名,
如果<logger-name>使用包名,那就意味着对该包下所有类统一设置日志级别。
如果<logger-name>使用类名,那就意味着对该类设置日志级别。
而level则可以是trace、debug、info、warn和error等级别。
【小技巧】实际项目开发时,尽量避免使用System.out.println来做输出,而应该用日志来做输出。
System.out.println 在输出的时候,每打印一行都是需要进行IO的,所以会很耗性能。
如果你在调试时用了大量的System.out.println来做输出,到了项目上线时必须要删除这些输出语法,否则会因为IO造成性能影响。
但如果你用的日志(debug)来输出,项目上线时,只要将应用级别调高,这些日志输出就会被自动关闭,因此无需输出这些日志输出语句。
▲ 互联网上常问如何控制日志输出
Spring Boot让MyBatis输出它执行的SQL语句啊?非常简单:
logging.level.<Mapper组件所在包>=debug
组件可以理解是类
Spring Boot看到Redis的详细执行过程?非常简单:
logging.level.io.lettuce.core=debug
Spring Boot整合Redis默认使用Lettuce依赖,而io.lettuce.core就是Lettuce组件核心API所在的包。
Spring Boot看到MongoDB的详细执行过程?非常简单:
logging.level.***.mongodb=debug
上面***.mongodb就是MongoDB核心API所在的包。
由此可见,通过Spring Boot可以让它输出任意框架的执行过程,只需要如下设置
logging.leve.<框架核心API所在的包>=debug
代码示例:
1、先创建一个类,获取日志对象。
2、然后在application.yml配置类里面配置一些日志信息—改变Spring Boot的核心日志级别
通过debug=true或trace=true等属性(通过配置文件、命令行参数、系统变量、OS环境变量等方式)改变整个Spring Boot核心的日志级别。
如图:这里在配置文件里面设置核心日志级别为 trace = true,就是级别为 trace。
但是打印出来的还是只有 info、warn 和error,但是控制台的启动记录里面还是有trace的,如图
这个是改变项目程序组件的核心日志级别,设置特定包下所有类的日志级别,打印的时候就可以如图,把 trace 和 debug 都打印出来
这个是让controller包下面的所有类的日志级别设置为 trace
这个是让LogController这个类的日志级别设置为 trace
★ 日志输出到文件:
Spring Boot默认只将日志输出到控制台,不输出到文件,如果要将日志输出到文件,
可为Spring Boot设置如下两个属性的其中之一:
- logging.file.name:设置日志文件的文件名。
- logging.file.path:设置日志文件的目录。使用默认的spring.log作为文件名。
logging.file.path 这个有一个好处,就是当日志文件过大的时候,就会自动把日志文件分成多个文件。
代码示例:
- logging.file.path:设置日志文件的目录。使用默认的spring.log作为文件名。
这个就是生成在文件夹中的日志文件,跟控制台的打印出来的是一样的。
Logback设置
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: 保留多少天的日志归档(默认为7)
Java 的日志归档是指对生成的日志文件进行周期性或大小限制的管理,以便保留和存档旧的日志文件,以便后续的检查、分析和备份。
通常情况下,应用程序会生成大量的日志数据,这些日志文件会越来越大,占用系统存储空间。为了避免过多的日志文件影响系统性能和存储空间的占用,可以对日志进行归档管理。
具体来说,归档通常有以下几种方式:
基于时间的归档:按照一定的时间间隔(如每天、每周、每月)将日志文件进行归档,将旧的日志文件存档到特定的文件夹或压缩文件中,以便后续查阅。
基于大小的归档:当日志文件达到一定大小时,将当前的日志文件存档,然后重新创建一个新的日志文件,以确保日志文件的大小始终在一个可接受的范围内。
★ 日志组:
(1)将多个包定义一个组名,
(2)然后对整个组设置指定的日志级别
——这样即可将该组对应的所有包统一设置成相同的日志级别。
日志组也是一个提高项目可维护性的小技巧。
就是一个项目有很多个包(文件夹),比如 controller,service、dao、domain、config 等等,然后我们想让controller、service、dao这三个包的日志级别设置为 debug 级别。但是又不可能在配置文件中一个包一个包的写配置,所以这个时候就可以用到日志组。
代码示例:
需求:我这个项目有三个包c1,c2,c3,我想让 c2 和 c3 这两个包的日志级别为 warn ,然后项目的其他包的日志级别为trace。
这里建3个包
我配置让 c2 c3这两个包的日志级别为warn
项目其他包的日志级别为 trace,其他包不可能一个一个写出来,所以直接把最大的包 boot 进行设置。
但是 c2 c3 这两个包又被包含在 boot 包里面,所以要看看c2 c3 这两个包的日志级别是我们要的 warn 级别,还是会因为被boot包 包含而变成trace级别
如图可以看出 c2 c3 这两个包的日志级别没有被 boot 包影响,还是我们要的warn级别。
而项目的其他包,如 c1 ,就是我们要的 trace 级别
这两个设置,谁放上面谁放下面都没有影响各自的日志级别,不会有那种放下面然后覆盖上面的情况。
上面的日志实现就是基于 SLF4J + Logback:SLF4J是门面,Logback是实现
▲ 门面类(抽象层):SLF4J、JCL(Apache ***mons logging)、JBoss Logging
▲ 日志实现:Log4j、Log4j2、Logback、JUL(JDK内置的java.util.logging)
★ 如何替换默认的日志实现(Logback)
▲ 两步:
(1)去掉Logback依赖库,添加新日志实现的依赖库。
Logback日志实现的优先级最高,当该日志实现的JAR存在时,Spring Boot总会使用该JAR包作为默认的日志实现。
(2)在类加载路径的根路径下为新日志实现提供对应的配置文件。
默认从类加载路径的根路径下加载日志配置文件,也可通过logging.config属性来设置新的加载路径。
除了可根据底层依赖库自动选择日志实现外——根据JAR包来自动选择日志实现,找到哪个日志实现的JAR包,Spring Boot就是用哪个日志实现。
还可通过org.springframework.boot.logging.LoggingSystem属性显式指定日志实现,
该属性的值可以是LoggingSystem实现类的全限定名。
▲ 不同日志实现的配置文件:
Logback:logback-spring.xml、logback-spring.groovy、logback.xml或 logback.groovy
Log4j2: log4j2-spring.xml或log4j2.xml
JDK(JUL):logging.properties
Spring Boot 推荐 使用带-spring后缀的配置文件作为对应日志框架的配置文件。
★ 控制日志只输出到文件(不输出到控制台)
项目上线时比较实用!
两步:
(1)控制日志输出到文件。
指定logging.file.name或logging.file.path两个属性的其中之一。
(2)还需要显式提供日志实现对应的配置文件,通过该配置文件关闭日志在控制台的输出。
——这一步的配置文件往往应该是日志实现相关的,和Spring Boot关系并不大。
代码示例
1、创建一个 logback-spring.xml 配置文件,这个配置文件专门用来控制 logback 日志的,现在在这个配置文件进行配置,让日志不要输出到控制台,只输出到指定的文件就行
application.yml 的配置不需要改,还是那样。
启动项目,然后再访问方法,发现控制台都没有任何的日志输出,一片空白,然后打开日志输出的文件,发现成功只输出在文件中
如图:项目的启动时间是16:36分,文件中的日志也是同个时间,证明日志只输出在指定文件中,没有输出在控制台
logback-spring.xml配置文件
<!-- 关闭LogBack的日志在控制器的输出 -->
<configuration>
<!-- 导入Logback通用的日志配置 -->
<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>
上面用的是默认的 Logback,现在要改成 log4j2
★ 通过例子示范使用log4j2替换Logback
——比较小众的应用场景。用的比较少,因为 springboot 推荐用 SLF4J+Logback ,所以没必要改成其他的
但是这里可以尝试一下。
(1)去掉去掉Logback依赖库,添加Log4j2日志实现的依赖库。
(2)添加log4j2日志的配置文件——这一步是可选的。
代码示例
在创建项目的时候,就会默认有logback的日志依赖了,所以把这个logback的日志依赖从pom.xml文件中去除就可以了。
1、这个操作就是把springboot默认的日志排除在外(就是把logback排除在外)
2、添加新的日志实现
启动项目,发现日志输出和之前没有什么区别,因为更改日志实现,是底层实现的,不是具体的代码实现,可以理解为抽象的,所以用 logback 或者是 log4j2 ,只是底层实现方法变了,但是呈现出来的效果还是一样的。
如果:因为把logback 改成 log4j2 ,所以原本设置的 日志记录只输出到文件,不输出到控制台的作用,也失效了。
要看logback 和 log4j2 的区别,只能从maven 里面看了
改回来 logback ,原本设置的 日志记录只输出到文件,不输出到控制台的效果 就又恢复了
另一种日志打印方式:
在类上面添加注解 @Slf4j,那么就会有一个 log 对象,直接用 log.info 来打印日志就可以了。
@SpringBootApplication
@Slf4j
public class App {
public static void main(String[] args) {
var ctx = SpringApplication.run(App.class, args);
//普通控制台打印
System.err.println("普通打印myConfig01:"+ctx.getBean("myConfig01"));
//@Slf4j 日志打印,输出info级别的日志,日志只能输出字符串
//直接拿配置类这个bean,类名要小写
log.info("日志打印myConfig01:"+ctx.getBean("myConfig01"));
log.info("日志打印dataFormat:"+ctx.getBean("getDataFormat"));
}
普通控制台打印和日志打印效果