1. slf4j介绍
简单的讲就是slf4j是一系列的日志接口,而log4j、logback是具体实现了的日志框架。
因为是接口,所以在项目中如果你不引用log4j 、logback或者其它日志框架你会发现,控制台的输出是这样的
2. log4j和logback区别
log4j:是apache实现的一个开源日志组件。
logback:同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架。是slf4j的原生实现,也就是说logback实现slf4j是不消耗内存和计算开销的。
Logback替代log4J的十大理由:自行百度吧,总而言之,就是logback好用就对了。
以下是各种日志接口和SLF4J的关系。
unbound:未绑定的
underlying logging framework:底层日志框架
adaptation layer:适配层
native implementtation of a:a的本地实现
non-native implementation of a:非本地实现
3. logback介绍
Logback是由log4j创始人设计的又一个开源日志组件。Logback包括3个部分:
·logback-core(基础核心模块,其它两个模块的基础模块)
·logback-classic(log4j改良版,完整实现SLF4J API接口,可方便的与其他日志系统切换)
·logback-access(logback-access访问模块与Servlet容器集成提供通过Http访问日志的功能)
4.logback实际的使用
日常在开发的过程中,如果一个独立的模块(一个单独的完整的服务)涉及到好几个大的模块,比如用户管理模块,支付模块,订单模块,并且这几个模块日志很多,最好分开打印日志,这时候就需要分开成多个日志文件了,这时候需要怎么做呢?
(1) 文件的目录结构
三个模块:假设三个文件夹分别代表的是用户管理、支付、订单管理三个模块
Logs接口:各个模块日志的实现接口
配置文件:日志的回滚,基本配置在这里
(2)pom文件导入
这个包经常导入其它包的时候会导入,但是版本不是最新的,可以重新加依赖导一次<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.22</version>
</dependency>
<!--logback-classic包,该依赖会导入logback-core和logback-classic两个包-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!--logback-core包-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<!--logback-access包-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>1.2.3</version>
</dependency>
(3)logback.xml详解
<?xml version="1.0" encoding="UTF-8"?>
<!--scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。-->
<configuration scan="true" scanPeriod="60 seconds">
<!--定义变量 ,可被插入到logger上下文中,此处定义日志文件的存储地址-->
<property name="log.base.run" value="../logs/sshblog"/>
<!--JMX管理,logback支持使用JMX随时重载logback.xml或者单独设置某个package的levelscan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。-->
<jmxConfigurator/>
<!--输出到控制台-->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<!--日志格式化-->
<encoder>
<pattern>[sshblog]|%-20(%date|[%thread])|%-1level|%logger{80}| %msg%n</pattern>
</encoder>
<!--字符串System.out(默认)或者System.err-->
<target>System.out</target>
</appender>
<!--滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件-->
<appender name="logfileRun" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- <Encoding>UTF-8</Encoding> -->
<!--被写入的文件名-->
<File>${log.base.run}.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--当发生滚动时,决定RollingFileAppender的行为,涉及文件移动和重命名。属性class定义具体的滚动策略类,此处class为最常用的,其他的自己去看-->
<FileNamePattern>${log.base.run}_%d{yyyyMMdd}-%i.log.zip
</FileNamePattern> <!--必要节点,可以为活动文件和归档文件指定不同位置,当前日志总是记录到file指定的文件(活动文件),活动文件的名字不会改变-->
<MaxHistory>15</MaxHistory><!--可选节点,可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。-->
<TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><!--查看当前活动文件的大小,如果超过指定大小会告知RollingFileAppender 触发当前活动文件滚动-->
<MaxFileSize>50MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>[sshblog]|%-20(%date|[%thread])|%-1level| %msg [%file:%line]%n
</pattern>
</encoder>
</appender>
<logger name="com.test" level="trace" additivity="true"><!--用来设置某一个包或具体的某一个类的日志打印级别、以及指定appender。loger仅有一个name属性,一个可选的level和一个可选的addtivity属性。
name: 用来指定受此loger约束的某一个包或者具体的某一个类。
level: 用来设置打印级别,大小写无关。
addtivity: 是否向上级loger传递打印信息。默认是true。经测试,如果此处配置为true,且同一个appender同时添加在此和root,则会打印两次,如果根元素没有配置,则无论配置为true还是false,都只打印一次
-->
<appender-ref ref="stdout"/> <!--可以包含零个或多个appender-ref元素,标识这个appender将会添加到这个logger-->
</logger>
<logger name="com.xrom.ssh" level="error" additivity="true">
<appender-ref ref="stdout"/>
</logger>
<root level="trace"><!--它也是loger元素,但是它是根loger,是所有loger的上级。只有一个level属性,因为name已经被命名为"root",且已经是最上级了。
level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL和OFF,不能设置为INHERITED或者同义词NULL。 默认是DEBUG。-->
<appender-ref ref="logfileRun"/>
<!--<appender-ref ref="stdout" />-->
</root>
</configuration>
(4)Logs接口的详细实现
public interface Logs {
/**
* 控制台打印
*/
Logger CONSOLE = LoggerFactory.getLogger("console");
/**
* 用户相关的日志
*/
Logger USER = LoggerFactory.getLogger("ssh.user.log");
/**
* 物流相关的日志
*/
Logger LOGISTICS = LoggerFactory.getLogger("ssh.logistics.log");
/**
* 订单相关的日志
*/
Logger ORDER = LoggerFactory.getLogger("ssh.order.log");
}
(5)实际应用
public class Logistics {
private static final Logger LOGGER = LoggerFactory.getLogger(Logistics.class);
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
LOGGER.info("logistics common log");
Logs.LOGISTICS.info("logistics special log");
}
}
}
public class User {
private static final Logger LOGGER = LoggerFactory.getLogger(User.class);
public static void main(String[] args) {
LOGGER.info("user common log");
Logs.USER.info("user special log");
}
}
public class Order {
private static final Logger LOGGER = LoggerFactory.getLogger(Order.class);
public static void main(String[] args) {
LOGGER.info("order common log");
Logs.ORDER.info("order special log");
LOGGER.debug("order debug");
Logs.ORDER.info("order debug");
}
}
(6)运行结果
第一次:运行Logistics.main,运行结束后发现在D盘会创建Log文件夹,并且按Logback的配置文件,创建四个模块的目录,并且每个模块的日志文件已经创建好,打印对应的日志,如下所示
第二次:再运行order.main
我们发现debug日志没有打印,所以此时我们将logback中对应的日志级别由info改为debug再运行一次,如下所示。