日志的作用以及什么是日志
日志就是为了当程序出错的时候,程序员们可以通过日志看到是哪部分出现错误了,为了发现和定位问题。当然,我们还可以通过日志实现一些功能,如下:
- 记录系统的操作⽇志,⽅便数据恢复和定位操作⼈;
- 记录程序的执⾏时间,⽅便为以后优化程序提供数据⽀持;
- 记录⽤户登录⽇志,⽅便分析⽤户是正常登录还是恶意破解⽤户等。
在 Spring Boot 中,内置了日志框架(Slf4j),即让程序运行时可以通过控制台输出日志:
既然 Spring Boot 内置了日志框架,那么就可以通过框架来实现自定义日志的打印。
补充:
日志框架分为:日志门面、日志实现
- 日志门面框架:commons-logging、SLF4J. 这是日志的入口,是抽象层,不是具体的实现
- 日志实现框架:log4j、log4j2、JUL、logback. 这是日志的具体实现
在项目中,通常使用 日志门面 + 日志实现 实现日志。
自定义日志打印
分为两步:
- 在程序中得到日志对象;
- 使用日志对象打印日志。
代码实现:
@RestController
@RequestMapping("/log")
public class UserController {
// 1. 得到日志对象
private static final Logger logger = LoggerFactory.getLogger(UserController.class); // 通常为该类的类对象
@RequestMapping("/getLog")
public String printLog(){
System.out.println("不使用日志对象打印日志");
// 2. 通过日志对象打印日志
logger.info("<<< 使用日志对象打印日志>>>");
return "success";
}
}
在引入 Logger 接口和 LoggerFactory 类的时候需要注意引入 slf4j 这个包:
得到的输出结果如下:
日志是一长串的,它们分别都有不同的意思,格式如下:
其中,日志级别也是可以自己设定打印级别的,比如一些日志不太重要,当为默认日志级别(INFO)的话,在控制台中就会输出很多日志,当我们排查的时候就会产生干扰,此时可以通过设置不同的日志级别来提高我们维护以及判断正误的效率。下面将介绍都有哪些日志级别,以及如何使用。
日志级别
日志级别分为六种(从低到高):
- trace:微量,少许的意思,追踪信息,级别最低;
- debug:需要调试时候的关键信息打印;
- info:普通的打印信息(默认⽇志级别);
- warn:警告,不影响使⽤,但需要注意一些问题;
- error:错误信息,级别较⾼的错误⽇志信息,一般不影响系统继续运行;
- fatal:致命的,因为代码异常导致程序退出执⾏的事件,需要立即被处理的系统级错误。
Spring Boot 默认的日志级别就是 INFO 级别,即在控制台只会报告 info、warn、error、fatal 这几种级别的日志。
设置日志级别
1. 通过配置文件进行设置(yml、properties)
logging.level.root =error // properties 配置文件设置日志级别. 此处设置一个 error 级别的日志
当项目启动时,就只会出现 error 和 fatal 级别的日志(此处由于项目启动是正常的,就不会出现该日志):
yml 配置项:
logging:
level:
root: debug
就会发现输出了 debug 及以上级别的日志:
2. 通过日志框架进行设置
@RestController
@RequestMapping("/log")
public class UserController {
// 1. 得到日志对象
private static final Logger logger = LoggerFactory.getLogger(UserController.class); // 通常为该类的类对象
@RequestMapping("/getLog2")
public String printLog2(){
// 2. 通过日志对象打印日志
logger.debug("<<< debug 级别日志>>>");
logger.error("<<< error 级别的日志>>>");
logger.trace("<<< trace 级别的日志>>>");
logger.warn("<<< warn 级别的日志>>>");
logger.info("<<< info 级别的日志>>>");
return "success";
}
}
运行结果如下:
此时就会发现只出现了三种级别的日志,info、warn、error,没有出现 trance、debug,这就是 Spring Boot 的默认日志级别捣鬼,当我们没有设置默认日志级别时项目是 info 级别的,而 info 级别的日志不会输出 trance、debug 级别的日志,这也就说明了控制台为什么只输出上述三种级别的日志了。
接下来当我们通过配置文件设置项目默认日志级别为 debug,再次运行项目就会发现:
小结:当我们需要输出低级别的日志时(相比于 info),需要先在配置项里面配置默认日志输出级别,然后通过日志框架自定义日志级别才能完整的输出。
日志持久化
我们在项目中日志的输出都是在控制台上面的,而控制台伴随着项目重启就清除了,日志就没有了。在这里 Spring Boot 提供了可以让日志保存在硬盘里面的方法。
通过配置配置文件(yml、properties)
在项目中,可以通过在 yml 或者 properties 中配置持久化路径来保存日志:
# 日志的配置
logging:
level:
root: info # root 表示根目录,即整个项目的日志级别
file:
path: logger/ # 配置日志路径
也可以通过 name 属性来配置文件路径(绝对路径和相对路径都可)以及文件名称:
- 不设置路径,只设置名称:
# 日志的配置
logging:
level:
root: info # root 表示根目录,即整个项目的日志级别
file:
path: logger/ # 配置日志路径
name: test.log # 配置日志名称
就会保存在项目的根目录。
注意:
- 设置路径和名称:
# 日志的配置
logging:
level:
root: info # root 表示根目录,即整个项目的日志级别
file:
#path: logger/ # 配置日志路径
name: logger111/test.log # 配置日志路径及名称. 此处也可以设置绝对路径
日志文件分割
在配置文件里面进行配置(yml),如下:
# 日志的配置
logging:
level:
root: info # root 表示根目录,即整个项目的日志级别
file:
path: logger/ # 配置日志路径
name: logger111/test.log # 配置日志路径及名称
logback: # 设置日志分割
rollingpolicy:
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i # 分割的格式
max-file-size: 3KB # 满足多大进行分割
当运行项目的时候,日志文件大小达到 3 KB 的时候就会自动将日志文件进行分割,分割出来的日志文件会根据你在项目中设置的分割格式进行命名。
此处的 3 KB 不一定为 3 KB ,因为它是按一条一条的日志进行分割的,总不能因为分割半条日志而文件大小到了就不分割了,会保证日志的完整性。
此处只是简单介绍日志文件相关配置项,更多可以查看 Spring 官网。
更简单的日志输出(lombok @Slf4j)
上述对于日志的输出都需要两步(一是得到日志对象,二是根据日志对象进行输出),这样输出日志的时候,在每个类中都要先获取到该类的日志对象,就比较麻烦,而在引用 lombok 中的 @Slf4j 注解后,就不需要获取每个类的日志对象了。
首先需要现在 pom.xml 中引入 lombok 的依赖:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
然后通过注解输出日志即可,代码如下:
其中引入注解的时候需要引入 lombok 中的 @Slf4j 注解:
@Slf4j
@RestController
@RequestMapping("/log2")
public class UserController2 {
@RequestMapping("/getLog")
public String printLog(){
log.debug("<<< debug 级别日志>>>");
log.error("<<< error 级别的日志>>>");
log.trace("<<< trace 级别的日志>>>");
log.warn("<<< warn 级别的日志>>>");
log.info("<<< info 级别的日志>>>");
return "success";
}
}
启动项目,运行就可以将日志的输出了:
lombok 实现日志输出原理解释:
Java 程序在运行的时候首先是将用户写的代码(即 .Java 文件),编码成字节码文件(即 .class 文件),然后再通过 JVM 进行加载和运行。而 @Slf4j 这个注释就是在将 .Java 文件编码成 .class 文件后,生成了上述得到日志对象这样的代码,如下:
其实实际上还是通过两步来输出日志的(得到日志对象,通过日志对象进行输出)。
其中 .class 文件都会在 target 目录中: