日志的作用
- 发现和定位问题. 在程序的执行过程中,如果出现了错误,我们就可以轻松的找到这个bug
- 记录用户的登录日志 可以发现是正常用户还是恶意用户
- 记录系统的操作日志 方便数据恢复
- 记录程序的执行时间
SpringBoot的日志
我们在执行起项目的时候,我们发现,控制台有很多信息.其实这个就是日志了
通过上面的信息我们可以知道:
- SpringBoot内置了日志插件,可以直接打印日志了
- 日志打印在控制台上面,无法永久保存,
- 上面打印的是系统的日志,我们怎么进行自定义的日志设置
- SpringBoot内置的日志插件是
slf4j
常见日志框架
这个日志采用的是门面模式,看上去是使用的slf4j
,其实是它只是一个门面,代理人而已,真正的实现操作的SpringBoot中选用的是logback
下面是常见的日志门面:
commons-logging
slf4j(SpringBoot选用)
下面是常见的日志实现:
log4j 1/2
JUL
slf4j(Spring Boot选用)
自定义日志
1.得到日志对象
- 这个日志对象是Logger,注意是
org.slf4j
的类(这个是SpringBoot自己包含的一个日志插件)
- 使用LoggerFactory.getLogger(类对象)这个方法来获取Logger对象
//得到日志对象
private static final Logger logger= LoggerFactory.getLogger(TestController.class);
注意,这个日志对象是负责某一个具体的类的,打印日志的时候最先打印的就是类名
2.日志级别介绍
观察Logger的方法,我们会发现有很多种,其实这很多种方法对应不同的日志级别
- trace 少许的日志(最低级别)
- debug 调试期间的日志
- info 普通的日志(默认的全局日志的级别)
- warn 警告日志
- error 错误日志
- fatal 致命日志(系统级别,程序员不可以设置这个日志级别)
上面的六种日志的级别从低到高
private static final Logger logger= LoggerFactory.getLogger(TestController.class);
@RequestMapping("/test")
public void print(){
logger.trace("trace logger");
logger.debug("debug logger");
logger.info("info logger");
logger.warn("warn logger");
logger.error("error logger");
}
日志的打印结果是什么呢?
2022-07-21 16:42:43.011 INFO 136312 --- [nio-8080-exec-1] c.e.demo.Controller.TestController : info logger
2022-07-21 16:42:43.011 WARN 136312 --- [nio-8080-exec-1] c.e.demo.Controller.TestController : warn logger
2022-07-21 16:42:43.011 ERROR 136312 --- [nio-8080-exec-1] c.e.demo.Controller.TestController : error logger
我们观察到,只可以打印出info之后的日志.
原因是现在我们的全局级别设置的是info,所以就只能打印info之后的,它前面的不可以打印
1.改变全局日志级别
上面我们看到了只是打印了info级别之后的日志,我们可以改变全局日志级别之后,看一下会打印什么?
在appliaction.properties中设置全局级别为trace,
logging.level.root=trace
之后我们就会发现,有很多的日志全都打印出来了,这样我们就知道了如和改变日志的级别了
2.改变局部日志级别
上面注意我们改变的是root的级别,所以将所有的内容全部都打印了
但是如果我们只是先打印我们这个Controller包中的内容呢?
我们就可以改变路径,将root换位包名
# 设置全局
logging.level.root=error
# 设置局部
logging.level.com.example.demo.Controller=trace
加上了局部之后,我们就只打印Controller包中的trace级别的日志信息了
但是还有一点值得注意的是:
虽然全局的日志级别设置的是error大于局部的trace,但是在当前包下还是可以正确的打印,说明局部的优先级大于全局的优先级
持久化保存
上面的问题是日志都打印在控制台上面,不方便观看
另外,这个日志如果程序停止的话,就会丢失日志和数据,
所以我们最后要持久化保存,将日志保存在指定的磁盘上面
使用路径
如果我们只是指定保存的路径的话,springboot就会在路径那里自动的创建一个Spring.log文件,会将日志全部都放到那里
logging.file.path=D:/bit-java/logger
另外我们最后是写成反斜杠的形式,因为windows和linux都是支持反斜杠的.
而且使用斜杠\的话有可能会和之后的字符被认为是一个转义字符,所以我们最好使用反斜杠/
指定名字
我们也可以在指定目录的基础上再指定它的日志的名字
logging.file.name=D:/bit-java/logger/test.log
以.log为结尾的日志文件
另外,如果重新启动项目,此次打印的目录也会放到我们之前的日志文件中,而且是以追加的方式.
所以,很有可能几次这样之后这个日志文件中保存了大量的日志信息.
但是没有关系,这个文件有默认的大小(自己也可以设定)20GB,如果超过了这个范围系统会自动的帮助我们再开辟新的文件
使用Lombok进行打印日志
上面是一种打印日志的方法,但是在每一个类中都要实现Logger方法的话,就显得有一点麻烦了.好在Lombok可以帮助我们使用注解的方式更加方便的进行打印
1.有Lombok依赖
我们创建项目的时候安装了Lombok依赖,在pom.xml中有依赖.
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
2.使用@slf4j注解
- 在类名的前面添加@slf4j
- 直接使用log对象调用函数
@Controller
@ResponseBody
@Slf4j//加上Slf4j注解
public class TestController {
@RequestMapping("/test")
public void print(){
//直接使用log对象调用函数
log.info("info");
log.warn("warn");
log.error("error");
}
}
3.原理
target里面保存的是编译过的class文件.
我们可以看到经过编译过的TestController:
@Controller
@ResponseBody
public class TestController {
private static final Logger log = LoggerFactory.getLogger(TestController.class);
public TestController() {
}
@RequestMapping({"/test"})
public void print() {
log.info("info");
log.warn("warn");
log.error("error");
}
}
我们发现这个log其实是Lombok自动帮助我们进行创建的,引入Slf4j就是简化了这一步
这时我们也发现了我们的程序是经过我们自己写的代码和插件里面的代码一起进行组合的,将注解变为代码,然后再进行编译,编译成.class文件
Lombok常见注解
日志注解
@Slf4j 自动生成一个log对象
基本注解
@Getter
@Setter
@ToString
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@NoNull
@RequiredArgsConstructor(添加指定参数的属性)
组合属性
@Data 是上面基本注解的全部和
总结
这篇文章我们详细的讲解了如何自定义的打印日志和持久化的保存日志
其中自定义的打印日志我们可以使用LoggerFactory工厂来获取logger对象,也可以使用Lombok提供的SLf4j注解来帮助我们进行获取
另外,日志的等级也是非常的重要的,
trace,debug,info,warn,error,fatal
另外,我们还可以将日志持久化的进行保存,保存到本地中