好久没有写博客了。因为忙着搞项目,而且因为放假。猛然一回头,二月最后一天了,好快,该把这个月学到的东西该总结一下了。写博客既是加深一下记忆,另外是如果有错误希望大家能指出来。
一、为什么使用logback
logback作为log4j作者的另一款作品,避开了log4j的缺点。拥有更快的执行速度,某些场景下,logback的执行速度是log4j的10倍。
logback实现了slf4j。按我的理解,与log4j相比,slf4j与log4j整合的时候,会有一个中间的转换。而logback因为是slf4j的实现,所以没有了这层转换,能有更好的执行速率。
logback可以自动重新载入配置文件。我觉得这是挺棒的功能。不用去重启让配置文件生效,提高了开发效率。
更多关于logback的优点,点击这里。点击打开链接
二、logback的相关配置
(1)先来看一个logback相关的包。
|-logback-core:logback核心包,当你使用logback的使用,这个是必须的。
|-logback-classic:当你需要使用slf4j与logback整合的时候,就要使用这个包,它实现了slf4的api。
|-logback-access:当需要通过http访问日志的时候,需要加入这个包。
现在大部分情况下是slf4j+logback,所以以上的前两个包是经常被加上的,另外再带上slf4j的jar包。以下的内容都是logback与slf4j的整合。
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.24</version>
</dependency>
(2)logback编码中的使用:
Logger:用于记录日志,Logger一般为静态常量放在类中。
public class App {
private static Logger appLogger=LoggerFactory.getLogger(App.class);
private static Logger test = LoggerFactory.getLogger("test1");
public static void main(String[] arg) {
appLogger.info("hello");
test.info("hello");
}
}
上面是输出info级别的日志,对应的还有debug,warn,error。
得到logger对象可以通过上面两种方式,一个***.class,生成的logger是与它全路径的类名相对应的。这相当于logger的name。而第二个logger的name则为test1.。它是在配置文件中配置的。注意,这logger都是root的子logger。详细的会在下面介绍。
三、logback.xml的配置
logback日志输出的规则通过在根目录下面设置这样一个logback.xml指定。
看一个简单的配置。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="console" />
</root>
</configuration>
(1)根节点configuration:
它有三个属性:scan:默认为true,如果配置文件发生
scanPeriod:设置检测配置文件是否修改的时间,默认是毫秒,默认时间是1分钟
debug:默认为false,用于显示logback内部运行的状态
(2)appender:负责写日志,它有两个必须的属性name(指定名称),class指定使用的appender的全名
常见的appender有:
FileAppender:将日志输出到文件中。它下面的标签有:
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<!--指定文件地址与文件名-->
<file>F:/test.log</file>
<!--如果为true,被追加到文件末尾,如果为false,则清空现在的文件-->
<append>true</append>
<!--格式化输出-->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
<!--这个的说明在下方-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
ConseAppender: 将日志输出到控制台。
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!--格式化输出-->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--设置输出的方式,默认为System.out-->
<target>System.err</target>
</appender>
RollingFileAppender:滚动记录文件。
<appender name="ROLLFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<!--根据时间每秒生成一个日志文件-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--生成的文件名称是根据时间来生成的-->
<fileNamePattern>F:/log/%d{yyyy-MM-dd-HH-mm-ss}.log</fileNamePattern>
<!--最多可保存十个日志文件,当多了的话会覆盖之前最早的日志文件-->
<maxHistory>10</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
(3)logger(root):每个logger都是ch.qos.logback.classic.Logger的实例,每个logger都有一个名称,有一个级别level,一个additivity。root是根logger,它的名称就是root。一个logger可以有0个或多个appender。
name:决定logger的层次。root是最顶层的logger。其余的logger根据name进行分割。名为com的logger是root的子logger,com.sso的名称中,sso是com的子logger。这样父子logger构成了一个链。
level:日志级别按照从大到小分为别error>warn>info>debug:高级别的不会受到低级别的日志信息。
additivity:默认为true,表示这个logger接收到的消息是向上传到父logger中去。
<logger name="test1" level="info">
<appender-ref ref="STDOUT"/>
</logger>
<logger name="test2" level="info" additivity="false">
<appender-ref ref="STDOUT"/>
</logger>
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
</root>
public static void main(String[] arg) {
print("test1");
print("test2");
}
public static void print(String name) {
Logger logger = LoggerFactory.getLogger(name);
logger.info("222"); logger.debug("333");
}
输出结果如下:
2018-02-28 21:13:37.551 [main] INFO test1 - 222
2018-02-28 21:13:37.551 [main] INFO test1 - 222
2018-02-28 21:13:37.555 [main] INFO test2 - 222
其中通过子logger打印的日志,对于info,两者都可以拦截并进行打印。但test2拦截后拒绝向上传递,所以test2删除一次。而debug的级别低于info,所以连个子logger没有拦截到,更不会向上传递给root了。通过它我们可以灵活地将不同级别的日志输出到不同的位置。
ps:如有不对请指出~