目录
1.⽇志有什么⽤?
2.⽇志怎么⽤?
3.自定义日志打印
使⽤⽇志对象打印⽇志
日志格式说明
⽇志级别
⽇志使⽤
⽇志持久化
设置日志的保存路径
设置 日志文件的存储文件名
更简单的⽇志输出—lombok
1、 添加 lombok 框架⽀持。
2、 使⽤ @slf4j 注解输出⽇志
lombok 原理解释
补充:
Java 程序的运⾏原理图:
Lombok 的作⽤图:
lombok 更多注解说明
总结
⽇志是程序的重要组成部分,想象⼀下,如果程序报错了,不让你打开控制台看⽇志,那么你能找到报错的原因吗?
答案是否定的,写程序不是买彩票,不能完全靠猜,因此⽇志对于我们来说,最主要的⽤途就是排除和定位问题。
这就跟去医院看病一样,医生听了你的病情描述后,先定位一个方向,然后就让你做一些检查,来进一步确认他的猜想,从而锁定病情。
日志就像医生教你去做的检查,通过 这些 “检查的结果(日志)”来锁定病因(代码异常位置)。
除了发现和定位问题之外,我们还可以通过⽇志实现以下功能:
1、记录⽤户登录⽇志,⽅便分析⽤户是正常登录还是恶意破解⽤户。
假设有一个平台,一天被登录了10万次,登录日志暴增!
正常情况下,可能一天 ,顶多1 万多点。
但是,此时我们发现这一天的登录日志暴增,并且查到有好几个账号,在这一天里登录上万次!这还需要想嘛?肯定有人对着几个账号进行了暴力破解!(盗号)
我们马上就可以对其进行冻结操作,让真正的用户修改密码信息后,才能恢复正常使用。
甚至说:直接拉黑名单。
2、记录系统的操作⽇志,⽅便数据恢复和定位操作⼈。
试想一下:当某个人在某个时间段进行了一次错误操作,而操作日志会把这个操作的具体信息给记录下来了(操作人,操作时间,执行的操作,数据改动的前后状态)。
此时,我们就可以根据这个日志,锁定 执行该操作的人(bb 他一顿),让其 对 操作数据 进行 回滚(还原) 操作【根据日志的记录】。
3、记录程序的执⾏时间,⽅便为以后优化程序提供数据⽀持。
你可以理解为:日志,记录了每一个方法的执行时间(在一个统一的地方记录)。
就是说:记录每一个方法之前,我们先做一个拦截,每一个方法执行之后,再做一个拦截。
这样我们就能记录每一个方法的执行时间了。
那么,记录方法的执行时间有什么作用呢?
可以方便我们以后 对 程序进行针对性的优化。
公司里面的 主管/经理,每周都会做一件事:按照方法执行时间来对日志进行排序。
将执行时间最长的 前十个方法,挑出来进行优化。
要想进行优化,没有日志,你怎么知道哪些方法的运行时间很长。
更别提对这些方法进行优化,提升执行效率。
提升用户的体验感,等于 “痴人说梦”。
以上这些都是⽇志提供的⾮常实⽤的功能!!!
发现和定位问题,是日志 的 “ 程序属性 ”;
记录⽤户登录⽇志,记录系统的操作⽇志,记录程序的执⾏时间,是日志的“业务属性”。
这两种“属性”加一块,才是 日志 的用途(作用)。
其实在我们Spring Boot 项⽬在启动的时候默认就有⽇志输出,如下图所示:
只不过,上面这些日志,不具有持久化存储的特性。【没存储到 硬盘中】
简单来说:上述的这些日志,就是进行一个简单的打印,不会存储到硬盘。
也就是说 启动下一个项目的时候,上一次启动项目的日志是没有被记录下来的。
通过上述⽇志信息我们能发现以下 3 个问题:
1、Spring Boot 内置了⽇志框架(不然也输出不了⽇志)。
2、默认情况下,输出的⽇志并⾮是开发者定义和打印的,而是系统输出的日志,那开发者怎么在程序中⾃定义打印⽇志呢?
有的可能会说:使用 sout 输出语句进行打印,不就行了。
答案是不行的,因为 sout 语句 存在 几个问题!
第一个问题: sout 语句只能打印一些固定内容,所以很多日志的关键信息,sout 语句 拿不到的。
第二个问题: sout 语句 是不管处于哪种的情况下,它都会进行日志的输出的。这就会导致一个问题:有些时候,我们是需要屏蔽掉 日志的输出的!比如:我们处于一个本地开发的环境下,是需要去进行打印一些调制信息的。但是!在生产环境下,为了提升运行效率,是会把打印日志的操作给关闭掉的。此时,因为你使用的是 sout 语句,所以无论你是处于生产环境,还是开发环境,你都会进行一个日志的打印。
但是!如果我们使用了 日志框架,那么,我们是可以对 日志的级别 进行设置的这个级别的设置,你可以理解为: 对 日志打印 的一种限制!这么说吧: 日志的级别越低,打印的信息就越多[不管信息的重要程度,统一进行打印]:日志的级别越高,打印的信息就越少。[只打印重要信息: eror级别的日志
举个实例:假设 我们就是把 日志的等级,设置为 只显示 error 级别的日志。那么,我们在调试阶段 的 info 日志,或者是 debug 日志,它就不会输出了,也就是说:同一份代码,
放在 本地 运行的时候,能够很有效的打印 那些 debug 和 info的日志。
但是!放在线上的时候,将日志的级别设置成高级别之后,其它的代码都不需要我们去改,那些 debug 和 info的日志,都不会打印了。
除非,出现 error (错误) ,才会进行打印日志。
所以,我们不会说打印日志的时候,使用 sout 语句去打印!
而是,去使用 自定义的日志框架来打印!
3、⽇志默认是打印在控制台上的,⽽控制台的⽇志是不能被保存的,那么怎么把⽇志永久的保存下来呢?
Spring Boot ⾃定义打印⽇志的实现步骤:
1、在一个类中先获取到打印日志对象,日志对象 是 日志框架 提供的,而日志框架默认已经集成到 Spring Boot 里面了。(Spring Boot 内置了日志框架)
2、使⽤⽇志对象提供的方法实现日志的打印。
接下来我们分别来看
准备工作:创建一个 Spring Boot 项目,并在其中创建一个UserController类,用来演示
这个前面已经介绍过了,我直接一套流程给你。
接下来就是删除不必要的文件。
在启动类所处于的“根目录”下,创建一个子目录 controller,并且在其中创建一个 UserController 类
还没完,我们需 这个类 注入到 Spring Boot 中,因此,我们需要使用五大类注解中任意一个。
在这个类中添加一个 sayHi 方法,完善一下这个类。
在程序中得到⽇志对象
因为 Spring Boot 中内置了⽇志框架 Slf4j,所以咱们可以直接在程序中调⽤ slf4j 来输出⽇志。
常⻅的⽇志框架说明(了解)
大家,其实可以看到 日志 可以分为两个部分:日志门面 和 日志实现。
那么,问题来了: Spring Boot 中。明明只需要加了一个 日志框架 就行了,为什么要加两个?
这就会涉及到 设计模式中的 门面模式了
门面模式:相当于我们在真正操作之前,前面有一个代理对象。然后,所有的类在操作的时候,操作的是代理对象,而不是类。Ps:这就有点像 JDBC,不管你使用的是哪种数据库。都无所谓!最终我都是以 JDBC 的形式 进行 操作。[写法是固定的]
SLF4J 就是相当于 是 JDBC,不管你底下的框架是什么,我上面就是一个 SLF4J。[代码是不用改]另外,其实 门面模式 SLF4J 是不做事的,真正打印日志的不是它! !!
SLF4J 起到的作用:就是 驱动某一个日志进行打印的。
总结:
Spring Boot 采用的是 门面模式,它集成了2个框架。
用户感知的,去操作的是 SLF4J,但是最终去实现的是logback.至于logback 的 两个兄弟中, log4j 1/2 存在很多 bug,现在几乎没人用
另外,logback 和 log4j,是同一个团队开发的。只不过 log4j 问题太多,于是就有了 logback。[注意! log4j 和 logback,是两个完全不同的东西! ! ! ]
⽇志对象的打印⽅法有很多种(info,error,warn,trace,debug,getName…),我们可以先使⽤ info() ⽅法来输出⽇志
通过上述的日志打印效果,我们不难发现 使用 日志对象提供的方法,来打印日志的效果,非常好!因为它显示的信息非常详细!与系统打印的效果是一样的。
通过上述操作,我们完成了一个最简单基础的日志打印。
但是!日志具体表示什么信息呢?
⽇志级别是干什么用的呢?
1、筛选重要信息
比如:设置日志级别为 error,那么就可以只看程序的报错日志了。
对于普通的测试日志和业务日志就可以忽略了,从而节省开发者信息筛选时间。
2、控制不同环境下,一个程序是否需要打印日志。
如开发环境,我们需要详细的信息,而生产环境为了保证性能和安全性就会输入尽量少的日志,而通过日志的级别就可以实现此需求。
⽇志级别的分类与使⽤
⽇志的级别分为:
这种 致命级别的日志,都是由系统来进行自动打印的,不需要我们插手。
即:fatal 级别的日志,是不能自定义进行打印的。
⽇志级别的顺序:
越往下接收到的消息就越少。
这里需要拓展一下:
在有些资料中,认为 fatal 是 级别最低的,trace 是级别最高的。
这种说法,不能算错!只是看待的角度不一样而已。
它认为获取的信息越多,越详细,级别就越高。
我个人倾向于 fatal 是级别最高的,trace 是 级别最低的。
这就跟事物的危险等级一样,由低到高。 warn 的级别,很明显是比 fatal 的级别低的。
举一个形象一点的例子:
一个公司的老板无疑是级别最高的。
但是,老板会管闲事吗?
不会!没什么大问题(warn 和 fatal 级别的问题),老板一般都是做甩手掌柜的!
也就是 级别越高的人,他对一些细微的事物是并不关心的。
只关注大问题。
由于 系统 默认的日志级别为 info。控制台只会输出 日志等级 高于或等于 info 的 日志信息。
等级越高,输出的日志越少。
那么,怎么去设置日志的级别呢?
日志级别的设置
1、全局日志级别设置:
⽇志级别配置,只需要在配置⽂件中设置“logging.level”配置项即可。
前面程序,不是只输出 info 级别以上的日志的嘛。
现在,我们将 日志级别设置成最低的了。
此时执行程序会是什么效果呢?
我们再来将日志级别设置的高一点。
看看是不是像我们预期的那样:日志级别越高,打印的日志信息越少。
此时,我们就有个想法:我们能不能针对 某一个部分进行设置日志级别。
即:局部日志级别设置。
来看下面!
2、局部日志级别设置
还是通过 logger.lever 来进行设置!
不同的就是:将 root 修改成 你进行局部设置日志级别的对象(文件夹 / 类)。
现在有一个问题:在全局日志级别 和 局部日志级别,都被设置的情况下,哪一个的优先级最高?
局部日志级别设置,比 全局日志级别设置 的 优先级要高。
不过请放心,日常工作中,关于日志级别的设置,不会精确到类的!最多精确到 文件夹级别。
因为,以上的⽇志都是输出在控制台上的,而控制台上的信息是不会被存储到硬盘上的。
项目重启之后,之前的日志信息就没了。【打印完就没了!】
然⽽在⽣产环境上,我们是需要将⽇志保存下来的。
以便出现问题之后追溯问题,把⽇志保存到磁盘的过程就叫做持久化。想要将日志持久化,(将日志永久的保存到磁盘的某个位置):
1、在配置文件中设置日志的保存路径,当设置了保存路径之后,那么日志就会自动进行持久化存储。
2、在配置文件中设置日志保存的文件名,日志也会自动进行持久化存储。
还是通过 logging 来进行设置的。
不同的是:后面跟着的属性不同。
设置日志级别:level + 点 + 目录名称 / 类名 + “ = ” + 级别名称
而设置日志的保存路径:logging.file. path = '存储路径'
1、不要保存在C盘
2、不要出现中文和空格
3、使用反斜杠 /,或者两个斜杠 \\ 进行转义
就是把 path 改成 name 了。
下面我们来验证一下效果:
答案是没问题的!
而且,还有一个细节,来看!
得出结论:日志是通过 追加的方式来记录的。
但是!还存在一个问题!!!
如果 日志文件 很大(将所有的日志信息,都存储到一个文件夹里).
那我们查看起来,不就很麻烦了嘛!!!
那么,有什么方法是可以限制 日志文件的大小呢?
最为一个程序员,一般情况下是不用我们去设置的。
因为,日志文件的大小,默认是 10MB。
当日志文件大小超过了 10MB 的时候,会自动创建新的 日志文件。
其命名格式,就像我们创建副本一样:spring-boot(1).log,spring-boot(2).log,spring-boot(3).log…
 
另外,是可用通过上述的方法进行设置 日志文件的大小的。
每次都使⽤ LoggerFactory.getLogger(xxx.class) 很繁琐,且每个类都添加⼀遍,也很麻烦,这⾥讲⼀种更好⽤的⽇志输出⽅式,使⽤ lombok 来更简单的输出。
1、 添加 lombok 框架⽀持。
2、 使⽤ @slf4j 注解输出⽇志。
通过使用 lombok 提供的 SLF4J 注解,就能实现。
虽然我一开始就添加 lombok 框架。
但是!有些人说不定就没加呢??
下面,我来告诉大家一个技巧:
通过安装一个插件,即使我们在创建项目的时候,忘记添加某个框架的支持,也能通过这个插件来进行“补充”。
有了这个 Edit Starters 插件,以后,我们敲代码的时候,需要用到哪个 框架,就可以直接通过它来引入了。
回顾一下,前面输出日志的方法。
思考一下,为什么 加上 @Slf4j,就可以省略第一步,直接得到一个 log 对象呢?
基本注解
⽇志是程序中的重要组成部分,使⽤⽇志可以快速的发现和定位问题。
Spring Boot 内容了⽇志框架。
默认情况下使⽤的是 info ⽇志级别将⽇志输出到控制台的。
我们可以通过 lombok 提供的 @Slf4j 注解
和 log 对象快速的打印⾃定义⽇志.
⽇志包含 6 个级别:
trace:微量,少许的意思,级别最低;
debug:需要调试时候的关键信息打印;
info:普通的打印信息;
warn:警告,不影响使⽤,但需要注意的问题;
error:错误信息,级别较⾼的错误⽇志信息;
fatal:致命的,因为代码异常导致程序退出执⾏的事件。
⽇志级别依次提升,⽽⽇志级别越⾼,收到的⽇志信息也就越少,我们可以通过配置⽇志的保存名称或保存⽬录来将⽇志永久地保存下来。