为什么不使用 System.out.print
使用 System.out.print 也可以打印日志,帮助我们解决定位排查的问题。但是如果要解决记录用户操作记录等问题,System.out.print 就不能很好的满足需求了,就需要使用专门的日志框架
日志的用途
Spring Boot 项目在启动的时候默认就是有日志输出的,相比于 System.out.print 可以打印更多的内容
Spring Boot 内置了日志框架 Slf4j,我们可以在程序中通过调用 Slf4j 来输出日志
1. 打印日志 ----- Logger()
打印日志的步骤
(1) 获得日志对象
//在程序中获取日志对象需要使用日志工厂 LoggerFactory
private static Logger logger = LoggerFactory.getLogger(LoggerController.class);
LoggerFactory.getLogger 需要传递⼀个参数,标识这个日志的名称。这样可以更清晰的知道是哪个类输出的日志。当有问题时,可以更方便直观的定位到问题类
(2) 使用日志对象输出要打印的内容
@RestController
public class LoggerController {
private static Logger logger = LoggerFactory.getLogger(LoggerController.class);
@RequestMapping("/logger")
public void logger(){
logger.info("要输出的日志");
}
}
2. 打印日志 ----- Lombok
引入依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
日志代码
lombok提供的 @Slf4j 会帮我们提供⼀个日志对象 log,直接使用即可
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class LogController {
public void log(){
log.info("--------------要输出⽇志的内容----------------");
}
}
门面模式(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("关闭餐厅灯");
}
}
日志级别代表着日志信息对应问题的严重性, 可以过滤自己想看到的信息,从而更快的筛选符合目标的日志信息,提高效率,节约时间
日志级别是开发人员设置的,用来给开发人员看的,通常与测试人员的 Bug 级别没有关系。
级别越高,接受的信息越少
public void printLog() {
logger.trace("================= trace ===============");
logger.debug("================= debug ===============");
logger.info("================= info ===============");
logger.warn("================= warn ===============");
logger.error("================= error ===============");
}
(1)SpringBoot 默认的日志框架是Logback,Logback没有 FATAL 级别, 它被映射到 ERROR
(2)出现fatal日志,表示服务已经出现了某种程度的不可用,需要需要系统管理员紧急介入处理。通常情况下, ⼀个进程生命周期中应该最多只有⼀次FATAL记录
结果发现,只打印了info, warn和error级别的日志
这与日志级别的配置有关,日志的输出级别默认是 info级别,所以只会打印大于等于此级别的同志, 也就是 info, warn和error
(1) 配置日志级别
日志级别配置只需要在配置文件中设置 “logging.level” 配置项即可
properties 和yml 只需要配置其中一个
# Properties配置
logging.level.root: debug
# yml 配置
logging:
level:
root: debug
(2) 日志持久化:把日志保存下来
持久化方式
【1】日志文件名
# Properties配置
logging.file.name: logger/springboot.log
# yml 配置
logging:
file:
name: logger/springboot.log
此时日志内容保存在了对应的目录下
【2】日志的存储目录
# Properties配置
logging.file.path: D:/temp
# yml 配置
logging:
file:
path: D:/temp
logging.file.name 和 logging.file.path 两个都配置的情况下, 只生效其⼀,以 logging.file.name 为准
(3) 配置日志文件分割
如果我们的日志都放在⼀个文件中, 随着项目的运行, 日志文件会越来越⼤, 需要对日志文件进行分割
如果不进行配置, 就走自动配置
默认日志文件超过10M就进行分割
配置项 | 说明 | 默认值 |
---|---|---|
logging.logback.rollingpolicy.file-name-pattern | 日志分割后的文件名格式 | ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz |
logging.logback.rollingpolicy.max-file-size | 日志文件超过这个大小就自动分割 | 10MB |
# Properties配置
logging.logback.rollingpolicy.file-name-pattern=${LOG_FILE}.%d{yyyy-MM-dd}.%i
logging.logback.rollingpolicy.max-file-size=1KB
# yml 配置
logging:
logback:
rollingpolicy:
max-file-size: 1KB
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i
(4) 配置日志格式
配置项 | 说明 | 默认值 |
---|---|---|
logging.pattern.console | 控制台日志格式 | %clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MMdd'T'HH:mm:ss.SSSXXX}}){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{${LOG_DATEFORMAT_PATTERN:-yyyy-MMdd'T'HH:mm:ss.SSSXXX}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx} |
# Properties配置
logging.pattern.console='%d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'
# yml 配置
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'
通常情况下, 咱们就使用默认的日志格式打印即可