文章目录
一、为什么要专门学习日志
- 当前用的不好:我们当前用sout打印出来的日志不详细、不规范
- 日志十分重要:
- 定位和发现作用:
- 系统监控:机器监控项目,人通过监控反馈的日志判断项目是否出错了
- 请求是可以被拦截的,日志可以记录这个请求的开始时间和结束时间,响应结果等
- 程序员可以根据这些日志,来判断当前项目是否出错
- 数据采集:日志其实就是数据
- 通过数据去定位和发现问题
- 通过对数据的分析进行系统监控
- 通过数据的采集去做【推荐】之类的操作
- 日志审计:依据国家安全要求,必须要去记录
- 日志在企业中的使用:
- 打印:打印到文件中
- 对日志进行分类:为了数据采集到【特定的日志】上
- 比如某一个用户登录了,浏览了XXX界面,此时可能就会有两个不同的日志了。一个是登录日志,另一个是浏览日志,我们从不同的日志采集数据,以提供不同的服务
- 借助消息队列,提高性能:如果所有的日志都需要系统去执行打印,会影响到我们的性能
- 消息队列就是阻塞队列,日志这方主需要给数据采集的那方发送日志即可,不管有没有收到(发送的执行速度快,慢的是处理的过程),由数据采集的人进行日志的消费。
二、日志的使用
2.1 日志分类
- 示例:Spring的日志只打印INFO及以上级别,项目日志则是DEBUG及以上级别
@RestController
public class IOController {
private Logger log = LoggerFactory.getLogger(IOController.class);
@PostConstruct
public void print(){
log.error("我是error日志");
log.warn("我是warn日志");
log.info("我是info日志");
log.debug("我是debug日志");
log.trace("我是trace日志");
}
}
logging:
level:
root: info # root表示根目录
com: # 表示com/example这个路径下只打印debug级别
example: debug
2.2 打印日志
使用sout打印
使用日志门面 — SLF4J
- 什么是SLF4J:
- SLF4J不是一个真实的日志框架实现,而是一个日志框架门面,具体实现是log4j、lo4j2、logback、jul等
- Spring已经帮我们集成了这个日志框架,Spring默认用logback。如果想使用其他的配置,可以通过【logging.config】引入外部的配置文件。
- SLF4J的作用:
- 未引入日志门面的情况:问题比较多
- 引入了日志门面:解耦
- 未引入日志门面的情况:问题比较多
- 方式一:使用工厂创建对象
- 关于包的选择:
- Logger:org.slf4j
- LoggeFactorr:org.slf4j
- LoggerFactory.getLogger(LoggerController.class):从日志工厂中获取一个关联LoggerController的日志对象
- LoggerFactory:表示一个日志工厂
- getLogger(LoggerController.class):传入
LoggerController.class
作为参数,来获取与LoggerController
类关联的Logger
实例。这确保了日志输出能够明确地指出日志是从哪里产生的(在这种情况下,是从LoggerController
类)- 通常情况下,是以当前类来指定的,可以方便我们去查找
- 关于包的选择:
@RestController
public class LoggerController {
//static这里的使用是个人习惯,并未优化什么
private static Logger log = LoggerFactory.getLogger(LoggerController.class);
@PostConstruct
public void print(){
System.out.println("打印日志");
log.info("=======我是日志框架打印的日志===================");
log.error("我是error日志");
log.warn("我是warn日志");
log.info("我是info日志");
log.debug("我是debug日志");
log.trace("我是trace日志");
}
}
- 方式二:使用@SLF4J注解
- 概述:
- 方法一优化的点:方式一是用工厂创建一个日志对象,然后调用方法打印。但既然Spring可以帮我们管理对象,既然也是可以知道当前是什么类,也就是说可以让Spring里默认注入当前对象。
- @Slf4j:Spring没有提供解决方法,但Lombok提供了@Slf4j注解
- 使用这个注解后,相当于执行了【private static Logger log = LoggerFactory.getLogger(当前类名)】代码,Spring能自动获取到当前类的对象。
- 我们可以根据编译后的内容,去查看@Slf4j的执行效果
- 关于依赖关系:Lombok 、Slf4j、Spring、日志实现之间是没有什么依赖关系,可以独立使用的。比如并不是说Lombok只能在Spring里使用,它们都只是一个框架。
- 概述:
@RestController
@Slf4j
public class LoggerController {
@PostConstruct
public void print(){
log.error("我是error日志");
log.warn("我是warn日志");
log.info("我是info日志");
log.debug("我是debug日志");
log.trace("我是trace日志");
}
}
- 关于更改日志的颜色:只能更改控制台的颜色,因为这是IDEA的支持,而不是日志的支持
- 方法:启动类设置 —> 添加VM options —> 添加【-Dspring.output.ansi.enabled=ALWAYS】命令
- 方法:启动类设置 —> 添加VM options —> 添加【-Dspring.output.ansi.enabled=ALWAYS】命令
2.3 日志持久化
-
什么是日志持久化:把日志长期保存下来
- 存储的类别,大致分为内存和外存。内存没有持久化,外存存储形式有很多种,比如数据库、文件等
-
如何把日志保存在文件里:logging.file.name进行设置,value值可以为相对路径或绝对路径
-
logging.file.path VS name:path可以用来设置路径
-
对这些配置项的理解:执行者是日志框架,而非SpringBoot
- Spring把SLF4J集成进来了,虽然我们配置的是Spring Boot的配置文件,但是给我们提供服务的依旧是SLF4J。也就是说,我们在SpringBoot配置完后,具体的执行者依旧是SLF4J。
2.4 配置日志文件分割
- 使用原理:如果日志文件全都放在一个文件中,日积月累这个文件就会很大,当文件太大时,会无法查看
- 如何分割:达到一定大小后分割或每天换一个路径分割
三、日志分级
3.1 什么是日志分级
- 为什么需要日志分级:程序员通过自行判断日志的重要性后分级,可以提高看日志的效率(看重点)
- 太多日志的弊端:日志会影响到我们的性能,如果打了太多日志,响应时间会拉长
- 日志级别的介绍:级别从高到低依次为: FATAL、ERROR、WARN、INFO、DEBUG、TRACE
- FATAL:致命信息,服务已经挂了,必须立即去处理。理论上,一个进程只能出现一个FATAL信息。
- ERROR:错误信息,不需要立即处理,但也不能长期不处理
- WARN:警告信息,不影响使用,但需要注意的问题
- INFO:普通信息,用于记录应用程序正常运行时的⼀些信息, 例如系统启动完成、请求处理完成等
- DEBUG:调试信息,需要调试时候的关键信息打印
- TRACE:追踪信息,比DEBUG更细粒度的信息事件。相当于进出个门都要汇报一下,级别太低,一般不用
- 开发人员VS测试人员的日志等级:
- 开发: 开发人员这边的日志等级是程序员自己判断的,也因此哪怕我们搞了好几个ERROR日志,也不代表程序出错
- 测试: 测试人员这边的日志等级是根据损失的多少来划分
3.2 日志分级的使用
- 为什么没有FATAL的选项:致命信息不需要汇报也看得出来,而且也不是说日志一汇报,程序员马上就看得到(不是一直在看监控),日志是有滞后性的
- 为什么打印出来的结果没有DEBUG和TRACE:
- DEBUG:Spring默认的日志级别是INFO,DEBUG比INFO级别低
- TRACE:Spring默认的日志级别是INFO,TRACE比INFO级别低
@RestController
public class IOController {
private Logger log = LoggerFactory.getLogger(IOController.class);
@PostConstruct
public void print(){
log.error("我是error日志");
log.warn("我是warn日志");
log.info("我是info日志");
log.debug("我是debug日志");
log.trace("我是trace日志");
}
}
3. 如何修改默认的Spring日志级别:
logging:
level:
root: debug # 但此时会打印出很多日志,我们也不是需要那么多日志
- 可以用ctrl + F在控制台中快速查找文本
三、两个设计模式介绍
设计模式与框架无关,是对一些常见问题的解决方法
3.1 工厂模式
- 使用场景:我们之前创建一个对象,都是是用new来创建。工厂模式则是让我们引用一个类后,由这个类来帮我们创建对象,就跟工厂生产商品一样。
3.2 门面模式(外观模式)
- 什么是门面模式:子系统的外部和内部的通信通过一个统一的对象进行,门面模式提供一个高层次的接口,使得子系统更易于使用
- SLF4J就是门面模式的一个典型例子(当然,它也运用了其他的设计模式)
- 使用时,我们不会去关注实现SLF4J的子系统是如何实现的,我们只会去用门面系统的接口。哪怕底下的都变了,我们也只需要知道SLF4J怎么用就行
- 门面模式的模拟实现:
- 门面模式的优点:
- 解耦:减少了系统间的相互依赖,子系统的变化不会影响到调用它的客户端
- 提高了安全性:可以灵活设定访问权限,可以让子系统全部不公开,只让门面系统去访问