Spring Boot 日志
本节目标
1. 了解日志文件的用途
2. 学习SpringBoot 日志文件的配置
1. 日志概述
为什么要学习日志
日志对我们来说并不陌生, 从JavaSE部分, 我们就在使用 System.out.print 来打印日志了. 通过打 印日志来发现和定位问题, 或者根据日志来分析程序的运行过程. 在Spring的学习中, 也经常根据控制台 的日志来分析和定位问题
随着项目的复杂度提升, 我们对日志的打印也有了更高的需求, 而不仅仅是定位排查问题.
比如需要记录一些用户的操作记录(一些审计公司会要求), 也可能需要使用日志来记录用户的一些喜好, 把日志持久化, 后续进行数据分析等. 但是 System.out.print 不能很好的满足我们的需求, 我们就 需要使用一些专门日志框架(专业的事情交给专业的人去做)
日志的用途
通过前面的学习, 我们知道日志主要是为了发现问题, 分析问题, 定位问题的, 但除此之外, 日志还有很多用途
1. 系统监控
监控现在几乎是一个成熟系统的标配, 我们可以通过日志记录这个系统的运行状态, 每一个方法的响应 时间, 响应状态等, 对数据进行分析, 设置不同的规则, 超过阈值时进行报警. 比如统计日志中关键字的数 量,并在关键字数量达到一定条件时报警,这也是日志的常见需求之一
2. 数据采集
数据采集是一个比较大的范围, 采集的数据可以作用在很多方面, 比如数据统计, 推荐排序等.
• 数据统计: 统计页面的浏览量(PV), 访客量(UV), 点击量等, 根据这些数据进行数据分析, 优化公司运营策略
• 推荐排序: 目前推荐排序应用在各个领域, 我们经常接触的各行各业很多也都涉及推荐排序, 比如购 物, 广告, 新闻等领域. 数据采集是推荐排序工作中必须做的一环, 系统通过日志记录用户的浏览历史, 停留时长等, 算法人员通过分析这些数据, 训练模型, 给用户做推荐
3. 日志审计
随着互联网的发展,众多企业的关键业务越来越多的运行于网络之上. 网络安全越来越受到大家的关 注, 系统安全也成为了项目中的一个重要环节, 安全审计也是系统中非常重要的部分. 国家的政策法规、 行业标准等都明确对日志审计提出了要求. 通过系统日志分析,可以判断一些非法攻击, 非法调用,以 及系统处理过程中的安全隐患
2. 日志使用

它打印的日志和 System.out.print 有什么不同呢
@RestController
public class LoggerController {
@RequestMapping("/logger")
public String logger(){
System.out.println("打印日志");
return "打印日志";
}
}
可以看到, 我们通过 System.out.print 打印的日志, 比 SpringBoot 打印的日志缺少了很多信 息
SpringBoot 内置了日志框架 Slf4j , 我们可以直接在程序中调用 Slf4j 来输出日志
2.1 打印日志
打印日志的步骤:
• 在程序中得到日志对象.
• 使用日志对象输出要打印的内容
2.1.1 在程序中得到日志对象
在程序中获取日志对象需要使用日志工厂 LoggerFactory,如下代码所示:
private static Logger logger = LoggerFactory.getLogger(LoggerController.class)
2.1.2 使用日志对象打印日志
日志对象的打印方法有很多种,我们可以先使用 info() 方法来输出日志,如下代码所示
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LoggerController {
private static Logger logger =
LoggerFactory.getLogger(LoggerController.class);
@RequestMapping("/logger")
public String logger(){
logger.info("--------------要输出日志的内容----------------");
return "打印日志";
}
}
打印日志效果展示:

2.2 日志框架介绍(了解)
SLF4J不同于其他日志框架, 它不是一个真正的日志实现, 而是一个抽象层, 对日志框架制定的一种规范, 标准, 接口. 所有SLF4J并不能独立使用, 需要和具体的日志框架配合使用
2.2.1 门面模式(外观模式)
SLF4J是门面模式的典型应用(但不仅仅使用了门面模式)
门面模式定义
门面模式(Facade Pattern)又称为外观模式, 提供了一个统一的接口, 用来访问子系统中的一群接口. 其主要特征是定义了一个高层接口, 让子系统更容易使用
门面模式的实现
场景: 回家, 我们会开各个屋的灯. 离开家时, 会关闭各个屋的灯
如果家里设置一个总开关, 来控制整个屋的灯就会很方便
public class FacadePatternDemo {
public static void main(String[] args) {
LightFacade lightFacade = new LightFacade();
lightFacade.lightOn();
}
}
/**
* 灯的门面
*/
class LightFacade{
private Light livingRoomLight = new LivingRoomLight();
private Light hallLight = new HallLight();
private Light diningLight = new DiningLight();
public void lightOn(){
livingRoomLight.on();
hallLight.on();
diningLight.on();
}
public void lightOff(){
livingRoomLight.off();
hallLight.off();
diningLight.off();
}
}
interface Light {
void on();
void off();
}
/**
* 客厅灯
*/
class LivingRoomLight implements Light{
@Override
public void on() {
System.out.println("打开客厅灯");
}
@Override
public void off() {
System.out.println("关闭客厅灯");
}
}
/**
* 走廊灯
*/
class HallLight implements Light{
@Override
public void on() {
System.out.println("打开走廊灯");
}
@Override
public void off() {
System.out.println("关闭走廊灯");
}
}
/**
* 餐厅灯
*/
class DiningLight implements Light{
@Override
public void on() {
System.out.println("打开餐厅灯");
}
@Override
public void off() {
System.out.println("关闭餐厅灯");
}
}
门面模式的优点
• 减少了系统的相互依赖. 实现了客户端与子系统的耦合关系, 这使得子系统的变化不会影响到调用它 的客户端;
• 提高了灵活性, 简化了客户端对子系统的使用难度, 客户端无需关心子系统的具体实现方式, 而只需 要和门面对象交互即可.
• 提高了安全性. 可以灵活设定访问权限, 不在门面对象中开通方法, 就无法访问
2.2.2 SLF4J 框架介绍
SLF4J 就是其他日志框架的门面. SLF4J 可以理解为是提供日志服务的统一API接口, 并不涉及到具体的 日志逻辑实现
不引入日志门面
常见的日志框架有log4J, logback等. 如果一个项目已经使用了log4j,而你依赖的另一个类库,假如是 Apache Active MQ, 它依赖于另外一个日志框架logback, 那么你就需要把logback也加载进去.
存在问题
1. 不同日志框架的API接口和配置文件不同, 如果多个日志框架共存, 那么不得不维护多套配置文件(这 个配置文件是指用户自定义的配置文件).
2. 如果要更换日志框架, 应用程序将不得不修改代码, 并且修改过程中可能会存在一些代码冲突.
3. 如果引入的第三方框架, 使用了多套, 那就不得不维护多套配置
引入日志门面
引入门面日志框架之后, 应用程序和日志框架(框架的具体实现)之间有了统一的API接口(门面日志框架 实现), 此时应用程序只需要维护一套日志文件配置, 且当底层实现框架改变时, 也不需要更改应用程序代 码
SLF4J 就是这个日志门面
总的来说,SLF4J使你的代码独立于任意一个特定的日志API,这是一个对于开发API的开发者很好的思想
2.2.3 日志级别的分类
日志的级别从高到低依次为: FATAL、ERROR、WARN、INFO、DEBUG、TRACE
• FATAL: 致命信息,表示需要立即被处理的系统级错误.
• ERROR: 错误信息, 级别较高的错误日志信息, 但仍然不影响系统的继续运行.
• WARN: 警告信息, 不影响使用, 但需要注意的问题
• INFO: 普通信息, 用于记录应用程序正常运行时的一些信息, 例如系统启动完成、请求处理完成等. • DEBUG: 调试信息, 需要调试时候的关键信息打印
• TRACE: 追踪信息 , 比DEBUG更细粒度的信息事件(除非有特殊用意,否则请使用DEBUG级别替代)
2.2.4 日志级别的使用
日志级别是开发人员自己设置的. 开发人员根据自己的理解来判断该信息的重要程度
类似公司管理, 通常由领导来判断什么样的事情需要汇报, 什么样的事情不需要汇报.
针对这些级别, Logger 对象分别提供了对应的方法, 来输出日志
/**
* 打印不同级别的日志
* @return
*/
@RequestMapping("/printLog")
public String printLog() {
logger.trace("================= trace ===============");
logger.debug("================= debug ===============");
logger.info("================= info ===============");
logger.warn("================= warn ===============");
logger.error("================= error ===============");
return "打印不同级别的日志" ;

结果发现, 只打印了info, warn和error级别的日志
这与日志级别的配置有关, 日志的输出级别默认是 info级别, 所以只会打印大于等于此级别的日志, 也就 是info, warn和error.
2.5 日志配置
上述是日志的使用, 日志框架支持我们更灵活的输出日志, 包括内容, 格式等
2.5.1 配置日志级别
日志级别配置只需要在配置文件中设置"logging.level"配置项即可,如下所示
后面课程中出现的配置, properties 和yml只需要配置其中一个即可
Properties配置
logging.level.root=debug
yml配置
logging:
level:
root: debu
重新运行上述代码, 观察结果

2.5.2 日志持久化
以上的日志都是输出在控制台上的, 然而在线上环境中, 我们需要把日志保存下来, 以便出现问题之后追 溯问题. 把日志保存下来就叫持久化
日志持久化有两种方式
1. 配置日志文件名 2. 配置日志的存储目录
配置日志文件的路径和文件名:
# 设置日志文件的文件名
logging:
file:
name: logger/springboot.log

配置日志文件的保存路径
yml配置
# 设置日志文件的目录
logging:
file:
path: D:/temp
这种方式只能设置日志的路径, 文件名为固定的spring.log
注意: logging.file.name 和 logging.file.path 两个都配置的情况下, 只生效其一, 以 logging.file.name 为准.
2.5.3 配置日志文件分割
如果我们的日志都放在一个文件中, 随着项目的运行, 日志文件会越来越大, 需要对日志文件进行分割.

logging:
logback:
rollingpolicy:
max-file-size: 1KB
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i
1. 日志文件超过1KB就分割(设置1KB是为了更好展示. 企业开发通常设置为200M, 500M等, 此处没 有明确标准)
2. 分割后的日志文件名为: 日志名.日期.索引
项目运行, 多打印一些日志, 日志分割结果:

2.5.4 配置日志格式
目前日志打印的格式是默认的

打印日志的格式, 也是支持配置的. 支持控制台和日志文件分别设置

配置项说明:
1. %clr(表达式){颜色} 设置输入日志的颜色
支持颜色有以下几种: • blue • cyan • faint • green • magenta • red • yellow
2. %d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}} 日期和时间--精确到毫秒
%d{} 日期
${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX} 非空表达式, 获取 系统属性 LOG_DATEFORMAT_PATTERN , 若属性 LOG_DATEFORMAT_PATTERN 不存在,则使 用 -yyyy-MM-dd HH:mm:ss.SSSXXX 格式, 系统属性可以 System.getProperty("LOG_DATEFORMAT_PATTERN") 获取
3. %5p 显示日志级别ERROR,MARN,INFO,DEBUG,TRACE.
4. %t 线程名. %c 类的全限定名. %M method. %L 为行号. %thread 线程名称. %m 或者 %msg 显示输出消息. %n 换行符
5. %5 若字符长度小于5,则右边用空格填充. %-5 若字符长度小于5,则左边用空格填充. %.15 若 字符长度超过15,截去多余字符. %15.15 若字符长度小于15,则右边用空格填充. 若字符长度超 过15,截去多余字符
设置了颜色, 却没有生效? 需要配置, 让idea支持控制台颜色显示
1. 打开启动配置


2. 添加VM options

3. 重新启动程序, 就发现控制台支持颜色了

logging:
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'
file: '%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n
项目运行, 观察日志变化:

3. 更简单的日志输出
每次都使用 LoggerFactory.getLogger(xxx.class) 很繁琐, 且每个类都添加一遍, lombok给我们提供了 一种更简单的方式
1. 添加 lombok 框架支持
2. 使用 @slf4j 注解输出日志
3.1 添加 lombok 依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
3.2 输出日志
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class LogController {
public void log(){
log.info("--------------要输出日志的内容----------------");
}
}
lombok提供的 @Slf4j 会帮我们提供一个日志对象 log, 我们直接使用就可以
4. 总结
1. 日志是程序中的重要组成部分,使用日志可以快速的发现和定位问题,Spring Boot 内容了日志框 架,默认情况下使用的是 info 日志级别将日志输出到控制台的,我们可以通过 lombok 提供的 @Slf4j 注解和 log 对象快速的打印自定义日志
2. 日志包含 6 个级别, 日志级别越高,收到的日志信息也就越少,我们可以通过配置日志的保存名称 或保存目录来将日志持久化
更多推荐




所有评论(0)