一、日志的作用
日志是程序的重要组成部分,想象一下,如果程序报错了,不让你打开控制台看日志,那么你能找到报错的原因吗
答案是否定的,写程序不是买彩票,不能完全靠猜,因此日志对于我们来说,最主要的用途就是排除和定位问题
除了发现和定位问题之外,我们还可以通过日志实现以下功能:
- 记录用户登录日志,方便分析用户是正常登录还是恶意破解用户。
- 记录系统的操作日志,方便数据恢复和定位操作人。
- 记录程序的执行时间,方便为以后优化程序提供数据支持。
以上这些都是日志提供的非常实用的功能
日志真实使用案例:
关键节点上的关键数据日志记录举例:例如教务系统,在注册时候不止要在教务系统添加一条用户记录,同时也会给论坛添加一条一模一样的用户记录,这样做的目的是为了实现一次注册,多处使用的目的。不需要用户在两边系统注册了,等于在程序中以极低的成本实现的用户数据的同步,但这样设计有一个致命的问题,用户在教务系统注册信息的时候,如果论坛挂了,那么用户的注册行为就会失败?因为用户在注册的时候需要同步注册到论坛系统,但论坛现在挂了,这个时候怎么办呢?
最简单的解决方案,教务系统在注册的时候,不管论坛是否注册成功,都给用户返回成功,那这个时候如果论坛注册失败了怎么办?非常简单,如果注册失败了,记录一下日志,等论坛恢复正常之后,把日志给论坛的管理人员,让他⼿动将注册失败的用户同步到论坛系统,这样就最低成本的解决了问题。这就是日志的重要作用
二、日志怎么用
Spring Boot 项目在启动的时候默认就有日志输出
以上内容就是 Spring Boot 输出的控制台日志信息。
通过上述日志信息我们能发现以下 3 个问题:
- Spring Boot 内置了日志框架(不然也输出不了日志)。
- 默认情况下,输出的日志并非是开发者定义和打印的,那开发者怎么在程序中自定义打印日志呢?
- 日志默认是打印在控制台上的,而控制台的日志是不能被保存的,那么怎么把日志永久的保存下来呢
三、自定义日志打印
1、使用日志对象打印日志
Spring Boot自定义日志的打印:
1). 在一个类中先获取到打印日志对象(日志框架提供的日志对象,而日志框架默认已经集成到Spring Boot 里了);
- 得到日志对象Logger ->Logger 对象是属于 org.slf4j 包下的,不要导入错包
- 因为 Spring Boot 中内置了日志框架 Slf4j,所以咱们可以直接在程序中调用 slf4j 来输出日志
2). 使用日志对象提供的方法实现日志的打印
- 在程序中获取日志对象需要使用日志工厂 LoggerFactory
- 日志工厂需要将每个类的类型传递进去,这样我们才知道日志的归属类,才能更方便、更直观的定位到问题类
@Controller
@ResponseBody // 非静态数据
public class UserController {
// 1、先得到日志对象——来自于slf4j
private final static Logger log =
LoggerFactory.getLogger(UserController.class); // 设置当前类的类型
@RequestMapping("/sayhi")
public void sayHi() {
log.trace("I'm trace");
log.debug("I'm debug");
log.info("I'm info");
log.warn("I'm warn");
log.error("I'm error");
}
}
访问 http://localhost:8080/sayhi,打印日志效果展示:
默认日志输出级别:
- 当前未配置文件中的日志设置,观察控制台输入的日志级别,得到以下结论,日志的输出级别,默认是 info
常⻅的日志框架说明(了解)
2、日志格式说明
四、日志级别与分类
1、什么是日志级别
日志的级别就是为了筛选符合目标的日志信息的。试想一下这样的场景,假设你一家 2 万人公司的老板,那么每人员工的日常工作和琐碎的信息都要反馈给你吗?一定不会,因为你根本没有那么多经历。
于是就有了组织架构,而组织架构就会分级,有很多的级别设置,如下图所示
有了组织架构之后,就可以逐级别汇报消息了,例如:组员汇报给组长;组长汇报给研发一组;研发一组汇报给 Java 研发,等等依次进行汇报。
而日志分级大概的道理也是一样的,有了日志级别之后就可以过滤自已想看到的信息了,比如设置日志级别为 error,那么就可以只看程序的报错日志了,对于普通的调试日志和业务日志就可以忽略了,从而节省开发者的信息筛选时间
2、日志级别分类
- trace:微量,少许的意思,级别最低
- info:普通的打印信息(默认级别)
- debug:需要调试时候的关键信息打印
- warn:警告,不影响使用,但需要注意的问题
- error:错误信息,级别较高的错误日志信息
- fatal:致命的,因为代码异常导致程序退出执行的事件 (系统输出的日志,不能自定义打印)
日志级别的顺序:
越往上接收到的消息就越少
3、日志使用
日志级别配置只需要在配置文件中设置 “logging.level” 配置项即可,配置根路径的日志级别,application.properties:
# 设置全局的日志级别
logging.level.root=trace
# 设置局部的日志级别
logging.level.com.example.springboot_logger=warn
注意: 当存在局部日志级别 和 全局的日志级别设置时,当访问局部日志时,使用的是局部日志级别,也就是局部日志级别优先级 > 全局的日志级别
五、日志持久化
# 设置全局的日志级别
logging.level.root=info
# 设置局部的日志级别
logging.level.com.example.springboot_logger.controller=trace
以上的日志都是输出在控制台上的,然而在生产环境上咱们需要将日志保存下来,以便出现问题之后追溯问题,把日志保存下来的过程就叫做持久化
**1). 在配置文件中指定日志的存储目录,**当设置了保存路径之后,Spring Boot 就会将控制台的日志写到相应的目录或文件下了
**2). 在配置文件中设置日志保存的名称,**日志会自动进行持久化
1、配置日志文件的保存路径
错误方式:logging.file.path=F:\Download
——SpringBoot会认为是一个特殊的字符,而非目录,所以日志持久化不会成功
——正确设置日志路径的方式 1:
# 配置日志文件的保存路径
logging.file.path=F:/Download
生成一个 spring.log
文件,vscode 打开:
——正确设置日志路径的方式 2:
# 配置日志文件的保存路径
# logging.file.path=F:/Download
logging.file.path=F:\\Download
删除此文件,重新运行,同样会生成 spring.log
文件
2、配置日志文件的文件名
# 设置日志文件的保存名称
# 1)
# logging.file.name=spring_boot.log
# 2) 指定目录
logging.file.name=F:\\Download\\spring_boot.log
生成一个 spring_boot.log
文件
日志数据默认是追加而不是覆盖,当日志数据变多,也不需要设置日志大小,当用满时,会自动以数字 123… 分割文件
综合练习:将 controller 包下 error 级别以上的日志保存到 log_all.log 下,将 service 下 warn
级别以上的日志保存到 log_all.log 下
实现的关键步骤:
- 不同包定义不同的日志级别。
- 使用日志对象打印所有类型的日志。
- 设置固定的日志保存文件名
六、更简单的日志输出—lombok
1、lombok
每次都使用 LoggerFactory.getLogger(xxx.class) 很繁琐,且每个类都添加一遍,也很麻烦,这里讲一种更好用的日志输出方式,使用 lombok 来更简单的输出
1). 添加 lombok 框架支持
——添加插件 EditStarters,
——使用 EditStarters 添加 lombok
2). 使用 @slf4j 注解输出日志
@Controller // 直接和前端交互,不能用 @Service
@ResponseBody
@Slf4j // 替代了 LoggerFactory.getLogger 操作
public class UserService {
@RequestMapping("/sayhi2")
public void sayHi() {
log.trace("I'm trace");
log.debug("I'm debug");
log.info("I'm info");
log.warn("I'm warn");
log.error("I'm error");
}
}
——设置日志级别配置 application.properties:
# 设置局部的日志级别
logging.level.com.example.springboot_logger.controller=trace
——访问 http://localhost:8080/sayhi2:
注意:使用 @Slf4j 注解,在程序中使用 log 对象即可输入日志,并且只能使用 log 对象才能输出,这是 lombok 提供的对象名
2、lombok 原理解释
lombok 能够打印日志的密码就在 target 目录里⾯,target 为项目最终执行的代码,查看 target 目录如下:
Java 程序的运行原理:
Lombok 的作用如下图所示:
3、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:微量,少许的意思,级别最低;
- info:普通的打印信息;
- debug:需要调试时候的关键信息打印;
- warn:警告,不影响使用,但需要注意的问题;
- error:错误信息,级别较高的错误日志信息;
- fatal:致命的,因为代码异常导致程序退出执行的事件。
日志级别依次提升,而日志界别越高,收到的日志信息也就越少,我们可以通过配置日志的保存名称或保存目录来将日志永久地保存下来