目录
[2.1 打印日志](#2.1 打印日志)
[2.1.1 在程序中获取日志对象](#2.1.1 在程序中获取日志对象)
[2.1.2 使用日志对象打印日志](#2.1.2 使用日志对象打印日志)
[2.2.1 门面模式(外观模式)](#2.2.1 门面模式(外观模式))
[2.2.2 门面模式的实现](#2.2.2 门面模式的实现)
[2.2.3 SLF4J 框架介绍](#2.2.3 SLF4J 框架介绍)
[2.3 日志格式的说明](#2.3 日志格式的说明)
[2.4 日志级别](#2.4 日志级别)
[2.4.1 日志级别的分类](#2.4.1 日志级别的分类)
[2.4.2 日志级别的使用](#2.4.2 日志级别的使用)
[2.5 日志配置](#2.5 日志配置)
[2.5.1 配置日志级别](#2.5.1 配置日志级别)
[2.5.2 日志持久化](#2.5.2 日志持久化)
[2.5.3 配置日志文件分割](#2.5.3 配置日志文件分割)
[三、 @Slf4j注解](#三、 @Slf4j注解)
[3.1 添加lombok依赖](#3.1 添加lombok依赖)
[3.2 输出日志](#3.2 输出日志)
一、日志的用途
1. 系统监控
监控现在⼏乎是⼀个成熟系统的标配, 我们可以通过日志记录这个系统的运⾏状态 ,每⼀个方法的响应 时间,响应状态等,对数据进行分析,设置不同的规则,超过阈值时进⾏报警.⽐如统计⽇志中关键字的数量,并在关键字数量达到⼀定条件时报警,这也是⽇志的常⻅需求之⼀。
2. 数据采集
数据采集是⼀个⽐较大的范围,采集的数据可以作⽤在很多⽅⾯,比如数据统计,推荐排序等.
• 数据统计:统计页面的浏览量(PV),访客量(UV),点击量等,根据这些数据进行数据分析,优化公司运营 策略
• 推荐排序: 目前推荐排序应⽤在各个领域,我们经常接触的各行各业很多也都涉及推荐排序,比如购 物,⼴告,新闻等领域.数据采集是推荐排序⼯作中必须做的⼀环,系统通过日志记录⽤户的浏览历史,停留时长等,算法⼈员通过分析这些数据,训练模型,给⽤户做推荐。
3. 日志审计
随着互联网的发展,众多企业的关键业务越来越多的运行于网络之上.网络安全越来越受到大家的关注,系统安全也成为了项目中的⼀个重要环节, 安全审计也是系统中非常重要的部分.国家的政策法规、行业标准等都明确对日志审计提出了要求.通过系统日志分析,可以判断⼀些非法攻击,非法调⽤,以及系统处理过程中的安全隐患.
二、日志使用
2.1 打印日志
2.1.1 在程序中获取日志对象
在程序中获取日志对象需要使用日志工程LoggerFactory,如下代码所示:
java
private static Logger logger = LoggerFactory.getLogger(LoggerController.class);
**注意:**Logger对象是属于org.slf4j包下的

2.1.2 使用日志对象打印日志
日志对象的打印方法有很多种,我们可以先使⽤info()方法来输出日志,如下代码所示:
java
package com.example.demo.controller;
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 门面模式(外观模式)
**门面模式(FacadePattern)**又称为外观模式,提供了⼀个统⼀的接⼝,⽤来访问子系统中的⼀群接口. 其主要特征是定义了⼀个⾼层接口,让子系统更容易使用.

门面模式主要包含2种角色:
外观角色(Facade): 也称门面角色,系统对外的统一接口,
**子系统角色(SubSystem):**可以同时有一个或多个SubSystem.每个SubSytem都不是一个单独的类,而是一个类的集合.SubSystem并不知道Facade的存在,对于SubSystem而言,Facade只是另一个客户端而已(即Facade对SubSystem透明)
举个例子:
比如去医院看病,可能要去挂号,门诊,化验,取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。

2.2.2 门面模式的实现
场景:
回家时,我们会开各个屋的灯离开家时,会关闭各个屋的灯 如果家里设置⼀个总开关,来控制整个屋的灯的打开与关闭就会很方便。
java
package FacadePattern;
public class FacadePatternDemo {
public static void main(String[] args) {
LightFacafe lightFacafe = new LightFacafe();
lightFacafe.lightOn();
lightFacafe.lightOff();
}
}
interface Light {
void on();
void off();
}
/*
* 灯的门面
* */
class LightFacafe {
private Light livingRoomLight = new LivingRoomLight();
private Light hallLight = new HallLight();
private Light dingingLight = new DingLight();
public void lightOn() {
livingRoomLight.on();
hallLight.on();
dingingLight.on();
}
public void lightOff() {
livingRoomLight.off();
hallLight.off();
dingingLight.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 DingLight implements Light {
@Override
public void on() {
System.out.println("打开餐厅的灯");
}
@Override
public void off() {
System.out.println("关闭餐厅的灯");
}
}
门面模式的优点
1、减少了系统的相互依赖.实现了客户端与子系统的耦合关系,这使得子系统的变化不会影响到调用它的客户端;
2、提高了灵活性,简化了客户端对子系统的使用难度,客户端无需关心子系统的具体实现方式, 而只需要和门面对象交互即可.
3、提高了安全性.可以灵活设定访问权限,不在门面对象中开通方法,就无法访问
2.2.3 SLF4J 框架介绍
SLF4J 就是其他日志框架的门面.SLF4J可以理解为是提供日志服务的统一API接口,并不涉及到具体的 日志逻辑实现.
引入日志门面
引入门面日志框架之后,应用程序和日志框架(框架的具体实现)之间有了统一的AP接口(门面日志框架实现),此时应用程序只需要维护一套日志文件配置,且当底层实现框架改变时,也不需要更改应用程序代码.

SLF4J 就是这个日志门面. 总的来说,SLF4J使你的代码独立于任意⼀个特定的日志API,这是⼀个对于开发API的开发者很好的思想.
2.3 日志格式的说明

2.4 日志级别
2.4.1 日志级别的分类
日志的级别从高到低依次为:FATAL、ERROR、WARN、INFO、DEBUG、TRACE
FATAL:致命信息,表示需要立即被处理的系统级错误。
ERROR:错误信息,级别较⾼的错误日志信息,但仍然不影响系统的继续运行。
WARN:警告信息,不影响使用,但需要注意的问题。
**INFO:普通信息,**用于记录应用程序正常运行时的⼀些信息,例如系统启动完成、请求处理完成等。
DEBUG:调试信息,需要调试时候的关键信息打印。
TRACE:追踪信息,比DEBUG更细粒度的信息事件(除非有特殊用意,否则请使用DEBUG级别替代)
日志级别通常和测试人员的Bug级别没有关系,日志级别是开发人员设置的,用来给开发人员看的.日志级别的正确设置, 也与开发人员的工作经验有关.如**果开发人员把error级别的日志设置成了info,就很有可能会影响开发人员对项目运行情况的判断.**出现error级别的日志信息较多时,可能也没有任何问题,测试的bug级别更多是依据现象和影响范围来判断。
日志级别的顺序:

2.4.2 日志级别的使用
日志级别是开发⼈员自己设置的.开发⼈员根据自己的理解来判断该信息的重要程度
针对这些级别,Logger对象分别提供了对应的方法,来输出日志.
java
@RestController
public class LoggerController {
private static Logger logger = LoggerFactory.getLogger(LoggerController.class);
@RequestMapping("/printLog")
public String pringtLog() {
logger.trace("======trace======");
logger.debug("======debug======");
logger.info("======info======");
logger.warn("======warn======");
logger.error("======error======");
return "打印不同级别的日志";
}
}
SpringBoot默认的日志框架是Logback,Logback没有FATAL级别,它被映射到ERROR
出现fatal日志,表示服务已经出现了某种程度的不可用,需要需要系统管理员紧急介入处理.通常情况下,一个进程生命周期中应该最多只有一次FATAL记录.
观察打印的日志结果:
结果发现,只打印了info,warn和error级别的日志这与日志级别的配置有关,日志的输出级别默认是info级别,所以只会打印大于等于此级别的日志,也就是info,warn和error.
2.5 日志配置
2.5.1 配置日志级别
⽇志级别配置只需要在配置⽂件中设置"logging.level"配置项即可,如下所示例。
Properties配置
java
logging.level.root=debug
yml配置
java
logging:
level:
root=debug:
运行结果:

2.5.2 日志持久化
配置文件名的路径和文件名
Properties配置
java
logging.file.name=logger/springboot.log
yml配置
java
logging:
level:
root=debug:
file:
name: logger/springboot.log
运行结果显示,日志内容保存在对应的目录下

配置日志文件的保存路径
Properties配置
java
logging.file.path=D:/temp
yml配置
java
logging:
file:
path: C:\logger
运⾏程序,该路径下多出⼀个日志文件:spring.log

注意:
logging.file.name 和 logging.file.path 两个都配置的情况下,只⽣效其⼀ ,以 logging.file.name 为准
2.5.3 配置日志文件分割
如果我们的日志都放在⼀个⽂件中,随着项⽬的运行,日志⽂件会越来越⼤,需要对日志文件进行分割
|-------------------------------------------------|------------------|----------------------------------|
| 配置项 | 说明 | 默认值 |
| logging.logback.rollingpolicy.file-name-pattern | ⽇志分割后的⽂件名 格式 | ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz |
| logging.logback.rollingpolicy.m ax-file-size | 日志文件超过这个大 小就自动分割 | 10MB |
Properties配置
java
logging.logback.rollingpolicy.file-name-pattern=${LOG_FILE}.%d{yyyy-MM-dd}.%i
logging.logback.rollingpolicy.max-file-size=1KB
yml配置
java
logging:
file:
path: C:/logger
logback:
rollingpolicy:
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i
max-file-size: 1KB
-
⽇志⽂件超过1KB就分割(设置1KB是为了更好展示.企业开发通常设置为200M,500M等,此处没 有明确标准)
-
分割后的⽇志⽂件名为:日志名.日期.索引
多次运行程序 查看日志分割效果

2.5.4 配置日志格式
打印日志的格式,也是支持配置的.支持控制台和日志文件分别设置
|-------------------------|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 配置项 | 说明 | 默认值 |
| logging.pattern.console | 控制台日志格式 | %clr(%d{S{LOG_DATEFORMAT_PATTERN:-yyyy-MM- dd'T'HH:mm:ss.SSSXXX)H){faint} %clr({LOG_LEVEL_PATTERN:- %5p}) %clr({PID:- )(magenta} %clr(---)(faint} %clr([%15.15t]) {faint} %clr(%-40.40logger{39}){cyan}%clr(:){faint} %m%n{LOG_EXCEPTION_CONVERSION_WORD:-%wEx} |
| logging.pattern.file | 日志文件 的日志格 式 | %d{S{LOG_DATEFORMAT_PATTERN:-yyyy-MM- dd'T'HH:mm:Ss.SSSXXX}{LOG_LEVEL_PATTERN:-%5p}${PID:-} ---[%t] %-40.40logger{39] : %m%nS{LOG_EXCEPTION_CONVERSION_WORD:-%wEx} |
配置项说明:
1.%clr(表达式){颜色}设置输入日志的颜色
支持颜色有以下几种:
blue
cyan
faint
green
magenta
red
yellow
2.%d[S[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类的全限定名.%Mmethod.%L为行号.%thread线程名称.%m或者%msg显示输出消息.%n换行符
5.%5若字符长度小于5,则右边用空格填充.%-5若字符长度小于5,则左边用空格填充.%.15若
字符长度超过15,截去多余字符.%15.15若字符长度小于15,则右边用空格填充.若字符长度超
过15,截去多余字符
更多说明,参考:https://logback.qos.ch/manual/layouts.html#conversionWord
修改控制台颜色显示
添加 VMoptions-Dspring.output.ansi.enabled=ALWAYS

在控制台中的显示
三 @Slf4j注解
3.1 添加lombok依赖
java
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
3.2 输出日志
java
@Slf4j
@RestController
public class LoggerController {
// private static Logger logger = LoggerFactory.getLogger(LoggerController.class);
@RequestMapping("/printLog")
public String pringtLog() {
log.info("---info---");
return "打印不同级别的日志";
}
}
lombok提供的 @Slf4j注解 会帮我们提供⼀个日志对象log,我们可以直接使用
