JavaEE进阶 - Spring Boot 日志文件 - 细节狂魔

1.⽇志有什么⽤?

⽇志是程序的重要组成部分,想象⼀下,如果程序报错了,不让你打开控制台看⽇志,那么你能找到报错的原因吗?

答案是否定的,写程序不是买彩票,不能完全靠猜,因此⽇志对于我们来说,最主要的⽤途就是排除和定位问题。

这就跟去医院看病一样,医生听了你的病情描述后,先定位一个方向,然后就让你做一些检查,来进一步确认他的猜想,从而锁定病情。

日志就像医生教你去做的检查,通过 这些 “检查的结果(日志)”来锁定病因(代码异常位置)。

除了发现和定位问题之外,我们还可以通过⽇志实现以下功能:

1、记录⽤户登录⽇志,⽅便分析⽤户是正常登录还是恶意破解⽤户。
假设有一个平台,一天被登录了10万次,登录日志暴增!
正常情况下,可能一天 ,顶多1 万多点。
但是,此时我们发现这一天的登录日志暴增,并且查到有好几个账号,在这一天里登录上万次!这还需要想嘛?肯定有人对着几个账号进行了暴力破解!(盗号)
我们马上就可以对其进行冻结操作,让真正的用户修改密码信息后,才能恢复正常使用。
甚至说:直接拉黑名单。

2、记录系统的操作⽇志,⽅便数据恢复和定位操作⼈。
试想一下:当某个人在某个时间段进行了一次错误操作,而操作日志会把这个操作的具体信息给记录下来了(操作人,操作时间,执行的操作,数据改动的前后状态)。
此时,我们就可以根据这个日志,锁定 执行该操作的人(bb 他一顿),让其 对 操作数据 进行 回滚(还原) 操作【根据日志的记录】。

3、记录程序的执⾏时间,⽅便为以后优化程序提供数据⽀持。
你可以理解为:日志,记录了每一个方法的执行时间(在一个统一的地方记录)。
就是说:记录每一个方法之前,我们先做一个拦截,每一个方法执行之后,再做一个拦截。
这样我们就能记录每一个方法的执行时间了。
那么,记录方法的执行时间有什么作用呢?
可以方便我们以后 对 程序进行针对性的优化。
公司里面的 主管/经理,每周都会做一件事:按照方法执行时间来对日志进行排序。
将执行时间最长的 前十个方法,挑出来进行优化。
要想进行优化,没有日志,你怎么知道哪些方法的运行时间很长。
更别提对这些方法进行优化,提升执行效率。
提升用户的体验感,等于 “痴人说梦”。

以上这些都是⽇志提供的⾮常实⽤的功能!!!

发现和定位问题,是日志 的 “ 程序属性 ”;记录⽤户登录⽇志,记录系统的操作⽇志,记录程序的执⾏时间,是日志的“业务属性”。
这两种“属性”加一块,才是 日志 的用途(作用)。


2.⽇志怎么⽤?

其实在我们Spring Boot 项⽬在启动的时候默认就有⽇志输出,如下图所示:
在这里插入图片描述
只不过,上面这些日志,不具有持久化存储的特性。【没存储到 硬盘中】
简单来说:上述的这些日志,就是进行一个简单的打印,不会存储到硬盘。
也就是说 启动下一个项目的时候,上一次启动项目的日志是没有被记录下来的。

通过上述⽇志信息我们能发现以下 3 个问题:

1、Spring Boot 内置了⽇志框架(不然也输出不了⽇志)。

2、默认情况下,输出的⽇志并⾮是开发者定义和打印的,而是系统输出的日志,那开发者怎么在程序中⾃定义打印⽇志呢?
有的可能会说:使用 sout 输出语句进行打印,不就行了。
答案是不行的,因为 sout 语句 存在 几个问题!

在这里插入图片描述

3、⽇志默认是打印在控制台上的,⽽控制台的⽇志是不能被保存的,那么怎么把⽇志永久的保存下来呢?


3.自定义日志打印

Spring Boot ⾃定义打印⽇志的实现步骤:

1、在一个类中先获取到打印日志对象,日志对象 是 日志框架 提供的,而日志框架默认已经集成到 Spring Boot 里面了。(Spring Boot 内置了日志框架)

2、使⽤⽇志对象提供的方法实现日志的打印。

接下来我们分别来看


准备工作:创建一个 Spring Boot 项目,并在其中创建一个UserController类,用来演示。

这个前面已经介绍过了,我直接一套流程给你。
在这里插入图片描述
接下来就是删除不必要的文件。
在这里插入图片描述
在启动类所处于的“根目录”下,创建一个子目录 controller,并且在其中创建一个 UserController 类
在这里插入图片描述
还没完,我们需 这个类 注入到 Spring Boot 中,因此,我们需要使用五大类注解中任意一个。
在这里插入图片描述
在这个类中添加一个 sayHi 方法,完善一下这个类。
在这里插入图片描述


在程序中得到⽇志对象

在这里插入图片描述
因为 Spring Boot 中内置了⽇志框架 Slf4j,所以咱们可以直接在程序中调⽤ slf4j 来输出⽇志。


常⻅的⽇志框架说明(了解)

在这里插入图片描述
在这里插入图片描述


使⽤⽇志对象打印⽇志

⽇志对象的打印⽅法有很多种(info,error,warn,trace,debug,getName…),我们可以先使⽤ info() ⽅法来输出⽇志
在这里插入图片描述
通过上述的日志打印效果,我们不难发现 使用 日志对象提供的方法,来打印日志的效果,非常好!
因为它显示的信息非常详细!与系统打印的效果是一样的。
在这里插入图片描述


日志格式说明

通过上述操作,我们完成了一个最简单基础的日志打印。
但是!日志具体表示什么信息呢?
在这里插入图片描述


日志级别

⽇志级别是干什么用的呢?

1、日志级别可以帮你筛选出重要的信息。

比如:设置日志级别为 error,那么就可以只看程序的报错日志了。
对于普通的测试日志和业务日志就可以忽略了,从而节省开发者信息筛选时间。

2、日志级别可以控制不同环境下,一个程序是否需要打印日志。

如开发环境,我们需要详细的信息,而生产环境为了保证性能和安全性就会输入尽量少的日志,而通过日志的级别就可以实现此需求。


⽇志级别的分类与使⽤

⽇志的级别分为:

trace:微量,少许的意思,级别最低;
debug:需要调试时候的关键信息打印;(调试日志)
info:普通的打印信息;(普通信息日志)【系统默认的日志级别】
warn:警告,不影响使⽤,但需要注意的问题;(警告日志)
error:错误信息,级别较⾼的错误⽇志信息;(错误日志)
fatal:致命的,因为代码异常导致程序退出执⾏的事件。

需要注意的是:
fatal 是不支持打印的,因为你程序都崩溃了,你还打印个锤子。。。
而且, 日志对象 也没有提供 关于 fatal 的 方法、
在这里插入图片描述
这种 致命级别的日志,都是由系统来进行自动打印的。
不需要我们插手。
即:fatal 级别的日志,是不能自定义进行打印的。


⽇志级别的顺序:

越往下接收到的消息就越少。
在这里插入图片描述

这里需要拓展一下:
在有些资料中,认为 fatal 是 级别最低的,trace 是级别最高的。
这种说法,不能算错!只是看待的角度不一样而已。
它认为获取的信息越多,越详细,级别就越高。

我个人倾向于 fatal 是级别最高的,trace 是 级别最低的。
这就跟事物的危险等级一样,由低到高。 warn 的级别,很明显是比 fatal 的级别低的。

举一个形象一点的例子:
一个公司的老板无疑是级别最高的。
但是,老板会管闲事吗?
不会!没什么大问题(warn 和 fatal 级别的问题),老板一般都是做甩手掌柜的!
也就是 级别越高的人,他对一些细微的事物是并不关心的。
只关注大问题。

而我们前面也测试了一下,输出 各个等级的 自定义 日志。
由于 系统 默认的日志级别为 info。
idea控制台,只会输出 日志等级 高于或等于 info 的 日志信息。
等级越高,输出的日志越少。

那么,fatal 的 情况,不就和 公司老板 的状态一样了!
一个只显示 程序崩溃信息,一个只关心大问题。
两者的共同就是 “偷油”!
只要 程序能跑,效果没问题,我的任务就完成了!
只要 不是公司不赚钱,或者要倒闭,就没我的事!

那么,怎么去设置日志的级别呢?


⽇志使⽤

日志级别的设置

全局日志级别设置

⽇志级别配置,只需要在配置⽂件中设置“logging.level”配置项即可。
在这里插入图片描述
前面程序,不是只输出 info 级别以上的日志的嘛。
现在,我们将 日志级别设置成最低的了。
此时执行程序会是什么效果呢?
在这里插入图片描述
我们再来将日志级别设置的高一点。
看看是不是像我们预期的那样:日志级别越高,打印的日志信息越少。
在这里插入图片描述
此时,我们就有个想法:我们能不能针对 某一个部分进行设置日志级别。
即:局部日志级别设置。
来看下面!


局部日志级别设置

方法也很简单!!!
还是通过 logger.lever 来进行设置!
不同的就是:将 root 修改成 你进行局部设置日志级别的对象(文件夹 / 类)。
在这里插入图片描述
现在有一个问题:
在全局日志级别 和 局部日志级别,都被设置的情况下,哪一个的优先级最高?

是 全局日志级别设置,直接全部覆盖! 局部日志级别设置,并没有生效!
即: 全局日志级别设置 比 局部日志级别设置 的 优先级要高!

还是 全局日志等级 的 设置,虽然起到了作用。
但是 设置了 局部日志级别 的 对象,遵守的是局部日志级别的设置。
即: 局部日志级别设置,比 全局日志级别设置 的 优先级要高。
在这里插入图片描述
很明显!
属于第二种情况:局部日志级别设置 的优先级,是高于 全局日志级别设置的。

不过请放心,日常工作中,关于日志级别的设置,不会精确到类的!
最多精确到 文件夹级别。


⽇志持久化

这么说吧,前面打印的日志,只是一闪而过!【打印完就没了!】

因为,以上的⽇志都是输出在控制台上的,而控制台上的信息是不会被存储到硬盘上的。
项目重启之后,之前的日志信息就没了。
在这里插入图片描述
然⽽在⽣产环境上,我们是需要将⽇志保存下来的。
以便出现问题之后追溯问题,把⽇志保存到磁盘的过程就叫做持久化。

想要将日志持久化,(将日志永久的保存到磁盘的某个位置):

1、在配置文件中设置日志的保存路径,当设置了保存路径之后,那么日志就会自动进行持久化存储。

2、在配置文件中设置日志保存的文件名,日志也会自动进行持久化存储。


设置日志的保存路径

还是通过 logging 来进行设置的。
不同的是:后面跟着的属性不同。
设置日志级别:level + 点 + 目录名称 / 类名 + “ = ” + 级别名称
而设置日志的保存路径:file+ 点 + path + “ = ” + 存储路径
在这里插入图片描述
另外,如果你不想使用 正斜杠 / ,就想使用 Windows 格式的 反斜杠 \ 也行,在前面多加一个反斜杠 \ 进行转义即可。
这个 稍微有点基础的朋友,应该都知道。


设置 日志文件的存储文件名

这个我就直接演示了。
就是把 path 改成 name 了。
在这里插入图片描述
下面我们来验证一下效果:
在这里插入图片描述
答案是没问题的!
而且,还有一个细节,来看!
在这里插入图片描述
得出结论:
日志是通过 追加的方式来记录的。

但是!还存在一个问题!!!

如果 日志文件 很大(将所有的日志信息,都存储到一个文件夹里).
那我们查看起来,不就很麻烦了嘛!!!

那么,有什么方法是可以限制 日志文件的大小呢?
这个问题,不是我们该操心的!
最为一个程序员,一般情况下是不用我们去设置的。

因为,日志文件的大小,默认是 10MB。
在这里插入图片描述
当日志文件大小超过了 10MB 的时候,会自动创建新的 日志文件。
其命名格式,就像我们创建副本一样:spring-boot(1).log,spring-boot(2).log,spring-boot(3).log…
 
另外,是可用通过上述的方法进行设置 日志文件的大小的。
在这里插入图片描述


更简单的⽇志输出—lombok

每次都使⽤ LoggerFactory.getLogger(xxx.class) 很繁琐,且每个类都添加⼀遍,也很麻烦,这⾥讲⼀种更好⽤的⽇志输出⽅式,使⽤ lombok 来更简单的输出。

1、 添加 lombok 框架⽀持。
2、 使⽤ @slf4j 注解输出⽇志。
通过使用 lombok 提供的 SLF4J 注解,就能实现。


1、 添加 lombok 框架⽀持。

虽然我一开始就添加 lombok 框架。
但是!有些人说不定就没加呢??

可能是在梦游,也可能觉得没必要添加。

下面,我来告诉大家一个技巧:
通过安装一个插件,即使我们在创建项目的时候,忘记添加某个框架的支持,也能通过这个插件来进行“补充”。
在这里插入图片描述
有了这个 Edit Starters 插件,以后,我们敲代码的时候,需要用到哪个 框架,就可以直接通过它来引入了。
这就很方便!很舒服!!!


2、 使⽤ @slf4j 注解输出⽇志。

回顾一下,前面输出日志的方法。
在这里插入图片描述


lombok 原理解释

思考一下,为什么 加上 @Slf4j,就可以省略第一步,直接得到一个 log 对象呢?
在这里插入图片描述


补充:

Java 程序的运⾏原理图:

在这里插入图片描述

Lombok 的作⽤图:

在这里插入图片描述


lombok 更多注解说明

基本注解

注解 作⽤
@Getter ⾃动添加 getter ⽅法
@Setter ⾃动添加 setter ⽅法
@ToString ⾃动添加 toString ⽅法
@EqualsAndHashCode ⾃动添加 equals 和 hashCode ⽅法
@NoArgsConstructor ⾃动添加⽆参构造⽅法
@AllArgsConstructor ⾃动添加全属性构造⽅法,顺序按照属性的定义顺序
@NonNull 属性不能为 null
@RequiredArgsConstructor ⾃动添加必需属性的构造⽅法,final + @NonNull 的属性为必需

组合注解

注解 作⽤
@Data @Getter + @Setter + @ToString +@EqualsAndHashCode +@RequiredArgsConstructor +@NoArgsConstructor

日志注解

注解 作⽤
@Slf4j 添加⼀个名为 log 的⽇志,使⽤ slf4j

总结

⽇志是程序中的重要组成部分,使⽤⽇志可以快速的发现和定位问题。
Spring Boot 内容了⽇志框架。
默认情况下使⽤的是 info ⽇志级别将⽇志输出到控制台的。

我们可以通过 lombok 提供的 @Slf4j 注解
和 log 对象快速的打印⾃定义⽇志.
⽇志包含 6 个级别:

trace:微量,少许的意思,级别最低;
debug:需要调试时候的关键信息打印;
info:普通的打印信息;
warn:警告,不影响使⽤,但需要注意的问题;
error:错误信息,级别较⾼的错误⽇志信息;
fatal:致命的,因为代码异常导致程序退出执⾏的事件。

⽇志级别依次提升,⽽⽇志级别越⾼,收到的⽇志信息也就越少,我们可以通过配置⽇志的保存名称或保存⽬录来将⽇志永久地保存下来。

猜你喜欢

转载自blog.csdn.net/DarkAndGrey/article/details/125932854