一. 什么是 Spring Boot 日志
Spring Boot 日志是指在 Spring Boot 应用程序中记录日志信息和跟踪应用程序执行过程的机制和工具. Spring Boot 集成了常用的日志框架, 如 Log4j、logback、Java Util Logging, 并提供了简单易用的配置方式, 使开发者能够方便的应用程序能够方便的应对应用程序的运行状态进行监控和面试.
下面就来看一个最简单的日志, 也是大家都见过最常见的日志, 在项目启动的时候, 日志其实就已经打印了, 只是没有持久化罢了
二. 日志的作用
从上面 Spring Boot 项目启动可以看到, 在启动的时候, 它打印了日志, 从日志里面我们可以看到一些信息, BUG 等级, 端口号等. 哪日志只有这些嘛 ? 当然不是了, 这里的简单的启动日志只记录了一些最基本的东西, 但日志还可以去干更多事
- 记录登陆日志, 利于分析用户是否正常登陆, 防止其恶意攻击破解用户
如果我们记录了登陆日志, 那么就可以从用户的登陆次数, 每次登陆是输入的次数, 在何地登陆等等, 来分析用户是否异地风险登陆, 多次暴力破解等问题
- 记录系统的操作日志, 方便数据恢复和定位操作
例如一个学校的教务系统, 记录每次系统的操作日志, 比如学生转班信息, 账户信息, 学籍管理等等. 当老师操作失误时, 比如将张三从 1 班 转到了 2 班, 这样就可以根据日志进行回滚操作进行数据的恢复, 同时可以定位到是哪个老师的错误操作出了问题进行追责等等
- 记录系统执行时间, 方便优化程序做数据支撑
记录一个程序开始时间, 在结束时也记录一下时间, 从而可以获取到该程序的执行时间. 执行时间过长, 那么需要考虑去如何优化它.
当然, 除了上面列举的一些作用, 日志还有其他重要用途, 大家可以自行探索
三. 如何自定义日志
当我在 TestController 中建立一个路由方法时, 去访问后, 在控制台输出了 打印日志 : XXX , 这是日志信息嘛 ?
相信肯定会认为, 在控制台输出了那就对了, 如果这个方法没输出那就错了. 光从这个层面上看, 好像确实是可以基础的定位到方法上, 但是从下面这些角度去看的时候就不这么认为了.
- 没有位置信息
该方法执行在那个位置不知道, 当我们在多出调用这个方法以后, 只通过控制台来简单的 sout 是很难定位到那个地方调用的这个方法出错了
- 没有时间信息
这是一个黑盒的模式, 没有时间, 不知道他是在执行前错误了还是执行和错误了
那么, 肯定还会有人认为, 我可以在每个方法下都输出不同的错误信息, 并且加上时间 sout 同样可以解决这个问题, 除了麻烦一点. 但是, 除了这两个问题, sout 还存在另外两个问题
- 没有级别设置
在生产中, 当出现错误以后, 更多的是想更直观的看到错误信息, 而不是调试错误信息, 没有办法设置日志级别进行信息的筛选,
- 不能持久化
这是最重要的问题, 当项目进行生产以后, 日志信息是很重要的信息, 它可以作为问题的分析基础, 是需要进行持久化的, 而 sout 是没有办法解决的, 重启以后就无法观察日志了
三. 如何使用日志
对于 Spring Boot 中, 它内置了 SLF4J 框架, 可以直接在程序中进行调用 SLF4J 来打印日志, 并且日志一个门面模式, 何为门面模式呢 ?
在这举例来说就像找房子一样, SLF4J 在这就充当了这个房屋中介的作用, 而它手下不同房子就是它的实现. 例如大平层( Log4j ) 、小洋房( logback ) 、海景别墅( Java Util Logging ). 某一天你需要租一个房子来装你得东西, 你就去找房屋中介, 房屋中介就会给你介绍上面的几种房屋类型, 你可以自己进行选择. 比如你选择了大平层, 你住腻了可以换一个通过中介在海景别墅, 这样你就可以省去找房子的时间, 想更换只需要通过中介进行更换就可以了
带入到我们的日志中, 中介就是日志的门面, 中介控制的房子就是日志的实现, 这样有什么好处呢 ? 我们不再需要去关注门面, 托管给别人帮我们做了, 只需要去看喜欢那个房子( 用什么日志方式去输出就行 ) 有一天住腻了 ( 这个日志方式出了问题 ) 就可以快速的通过中介在换一个房子( 换一个日志方式 ) , 避免在没有地方可以去( 你所有的日志都用的这个方法去控制, 没有中介那你想要换个房子就需要很长时间去修改 )
了解了日志得门面模式以后, 接下来看看如何自定义实现也给日志
- 得到日志对象
- 注意级别
通过上面得启动得系统日志可以看到, 他都是一类得, 因此获取的日志对象一定是类级别的日志对象, 并非只在某个具体的方法里去实现的方法级别对象
- 注意作用域
通过启动的系统日志可以看到, 日志的打印都是带有位置信息的, 你在哪个包那个类底下都是清楚的, 因此日志对象只能是私有的即只能在我这个类本身内去使用, 在别的类底下不好使, 否则日志就会乱了位置
- 注意框架的选择
由于我们在使用 SLF4J 作为门面模式时, 去创建日志对象需要通过门面去调用具体的实现方式, 因此创建日志对象时应当选择 SLF4J 下的 Logger
综上, 最终通过 SLF4J 的 Logger 创建一个 log 对象, 并通过提供的日志工程去调用 getLogger ( 因为是类级别的, 因此此处选择类的 getLogger 方法 )成功创建一个日志对象
- 使用 log 对象
访问路由后在控制台可以看到如下信息 :
PS : 日志信息打印此处和你们默认的不一样, 我在配置文件中设置了默认等级为 debug, 日志系统默认等级为 info, 下面会说这个问题, 此处只关注日志对象输出日志有哪些内容即可
时间信息、日志等级信息、日志位置信息、日志内容信息. 可以说是非常的齐全日志
四. 日志级别
- trace : 微量级别, 级别最低
- debug : 需要调试的时候使用, 调试级别
- info : 普通的打印信息 ( 日志默认的级别 )
- warn : 警告, 不影响使用, 但是需要注意的问题
- error : 错误信息, 级别比较高的错误日志信息
- fatal : 致命的, 因代码异常导致程序执行退出的事件
上面就是日志的级别, 但是我们能够操作的日志级别只有前五个, 最后一个致命的日志级别是无法操控的, 当程序错误退出的时候, 系统会自动帮我们打印 fatal 级别的日志信息.
从上之下, 级别是越来越高的, 越往下接收的消息越少, 遵守一个原则低级别的无法查看高级别的
可以看到, 只能查看到 info、warn 和 error 级别的错误信息, 而 trace 和 debug 是无法查看的, 这是为什么呢 ?
当我们把 info 注销掉在看看
可以看到, 只有 info 不见了, 在把 warn 和 error 注释掉看看
此时没有任何日志信息, 可以得到结论 日志的默认等级是 info, 哪当我们想查看 trace 和 debug 的日志信息怎么办呢 ? 毕竟调试日志对于写程序来说是很重要的, 可以定位问题所在, 下面就介绍一下 Spring Boot 中项目中日志的等级设置
五. 日志等级的设置
下面在 properties 配置文件中配置日志等级
或者在 yml 中设置日志等级
设置好以后, 在来执行观察看之前的 log 方法
由于我们已经在配置文件中设置了默认等级为 debug, 因此 debug 等级的错误日志信息我们也就可以看到了. 而比 debug 等级还低的 trace 日志信息仍然是无法查看的, 想要看就可以将配置信息中日志的等级设置为 trace
另外, 配置文件中除了 root( 根记录器 ) 设置为日志等级外, 还有更加详细的日志等级设置, 为特定的包设置日志等级, 例如下面这个配置文件中, 设置 com.example 包下的类日志等级为 info, 而 com.example.demo 包下的日志等级为 debug
六. 日志的持久化
当然, 日志如此重要不仅仅是因为它可以定位问题, 更重要的时候它可以作为数据分析, 想要数据分析肯定不能通过控制台 sout 的方式打印日志, 下次启动就没有了, 因此就必须将日志进行持久化, 下面就来实现日志的持久化操作
在 yml 配置文件中设置. 设置文件路径, 文件的名称可以不写( 写了生成的就是你设置的名称 ), 会自动生成一个名为 spring.log 的文件
再去运行刚刚的 log 方法, 此时在我刚刚的保存路径底下就生成了这样一个 spring.log 文件
当我重复去访问这个方法时, 它会重复打印日志, 我们来看看会不会覆盖
事实上, 它是不会覆盖的, 如果真的覆盖了那才是出大问题了 !
PS 1 : 在文件的保存路径设置中, 如果没有设置路径, 它会在项目底下生成一个你设置的名称的文件
PS 2 : 在官网中可以看到说明, 当日志文件超过 10MB 大小时, 它会将你后续得日志文件保存在一个新的文件中( 并且它会按照自己的命名规则替你命名和分割日志 ), 但是这个日志文件的大小也是可以去设置的
七. lombok 实现日志
可以看到, 在不同的类下去实现日志打印时, 都需要去创建日志对象, 修改 getLogger 方法的类对象, 会有点麻烦, 因此 lombok 就给我们提供了更简单的方式来实现日志的打印
- 添加 lombok 依赖
这一步都会, 手动添加即可 - 添加 @slf4j 注解
lombok 除了 @slf4j 注解外, 还有很多其它注解, 大家可以去官网查看.