在前面的学习中,控制台上打印出来的一大堆内容就是日志,可以帮助我们发现问题,分析问题,定位问题,除此之外,日志还可以进行系统的监控,数据采集等
在程序中获取日志对象需要使用日志工厂 LoggerFactory,然后调用 getLogger 方法,传入参数用来标识这个日志的名称,这样可以更清晰的知道是哪个类输出的日志
private static Logger logger = LoggerFactory.getLogger(CaptchaController.class);
System.out.println("System:" + code);
logger.info("Logger: " + code);
来看一下日志的格式:
应用名称可以在配置文件中进行配置
日志门面就相当于是淘宝 APP,日志实现相当于入驻的商家,在使用时是使用淘宝,真正提供商品的还是商家
也就是使用时使用 SLF4J,真正实现功能还是日志实现的框架
SLF4J 就是其他日志框架的门面,相当于提供日志服务的统一 API 接口,并不涉及到具体的日志逻辑实现,而是一个抽象层,对日志框架制定的一种规范、标准、接口。所有 SLF4J 并不能独立使用,需要和具体的日志框架配合使用。
如果说不引入 SLF4J 的话
引入门面日志框架之后,应用程序和日志框架之间有了统一的 API 接口,此时应用程序只需要维护一套日志文件配置即可,当底层实现框架改变时,也不需要修改应用程序代码
外观模式(门面模式)提供了一个统一的接口,用来访问子系统中的其他接口
SLF4J 就是外观模式的典型应用,但不仅仅使用了这一种设计模式
接下来以开灯的例子简单实现一下外观模式:
首先定义一个接口:
public interface Light {
void on();
void off();
}
然后定义两个实现类:
public class LivingRoomLight implements Light{
private static Logger logger = LoggerFactory.getLogger(LivingRoomLight.class);
@Override
public void on() {
logger.info("打开客厅灯");
}
@Override
public void off() {
logger.info("打开客厅灯");
}
}
public class BedroomLight implements Light{
private static Logger logger = LoggerFactory.getLogger(BedroomLight.class);
@Override
public void on() {
logger.info("打开卧室灯");
}
@Override
public void off() {
logger.info("打开卧室灯");
}
}
如果说是之前的实现模式的话,需要在 Main 方法中去分别创建这两个类的对象,然后调用方法,通过外观模式的话,可以创建一个类,用来实现之前的过程
public class LightFacade {
void lightOn(){
LivingRoomLight livingRoomLight = new LivingRoomLight();
livingRoomLight.on();
BedroomLight bedroomLight = new BedroomLight();
bedroomLight.on();
}
}
这样,即使实现类的方法发生改变,提供给用户使用的接口还是不变的,用户就不用考虑内部是怎么实现的
日志的级别从高到低依次为:FATAL、ERROR、WARN、INFO、DEBUG、TRACE。
创建 Logger 之后就可以调用方法区打印不同级别的日志,但是发现没有 fatal 级别的信息,因为出现这个问题已经很严重了,不用通过日志就可以知道出现问题了
运行之后发现 debug 级别和 trace 级别的日志没有打印出来,这是因为默认配置的日志级别是 info 级别的,所以比 info 级别低的就打印不出来
可以通过配置日志级别来设置
配置之后就可以看到级别低的日志了
也可以分类配置日志的级别,指定某个类的日志级别显示
logging:
level:
root: info
com:
example:
log:
controller: trace
在上面打印的日志中,如果把 idea 关了,那么之前打印的日志就没有了,如果说日志可以存储到文件中,也就是存储在硬盘上,就可以做到持久化,这样出现问题就可以查之前的日志
还是可以通过配置,来实现日志的持久化
第一种方式是通过配置文件名的方式
配置之后再运行的话,就会创建配置的文件夹和文件名,并且日志也存储在了文件中
还有一种方式是只设置路径
配置之后就会在设置的目录下创建一个 spring.log 文件夹,里面存储的就是日志信息
如果说所有日志都放在同一个文件中,那么这个文件肯定是越来越大的,就需要对日志文件进行分割,日志框架默认也设置了如果超过 10 M 就会分割
先来设置为 1KB 进行分割
分割之后的文件名也是可以指定的
logback:
rollingpolicy:
max-file-size: 1KB
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i
日志的格式也是可以控制的,
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'
直接使用注解@Slf4j
,然后就不用再创建 Logger 的对象了,直接就可以调用方法