常用日志处理工具
常见的 log 日志处理工具有:log4j、Logging、commons-logging、slf4j、logback。其中,commons-loggin、slf4j 是一种日志抽象门面,不是具体的日志框架;log4j、logback 是具体的日志实现框架。
一般使用 slf4j + logback 处理日志,也可以使用 slf4j + log4j、commons-logging + log4j 这两种日志组合框架。
日志级别
日志的输出都是分级别的,不同的场合设置不同的级别,以打印不同的日志。下面拿最普遍用的 log4j 日志框架来做个日志级别的说明,这个比较奇全,其他的日志框架也都大同小异。
log4j 的级别类 org.apache.log4j.Level 里面定义了日志级别,日志输出优先级由高到底分别为以下 8 种:

| 日志级别 | 描述 |
|---|---|
| OFF | 关闭:最高级别,不输出日志。 |
| FATAL | 致命:输出非常严重的可能会导致应用程序终止的错误。 |
| ERROR | 错误:输出错误,但应用还能继续运行。 |
| WARN | 警告:输出可能潜在的危险状况。 |
| INFO | 信息:输出应用运行过程的详细信息。 |
| DEBUG | 调试:输出更细致的对调试应用有用的信息。 |
| TRACE | 跟踪:输出更细致的程序运行轨迹。 |
| ALL | 所有:输出所有级别信息。 |
所以,日志优先级别标准顺序为:
ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
如果日志设置为 L ,一个级别为 P 的输出日志只有当 P >= L 时日志才会输出。
即如果日志级别 L 设置 INFO,只有 P 的输出级别为 INFO、WARN,后面的日志才会正常输出。
具体的输出关系可以参考下图:

Lombok
Lombok 是一种 java 实用工具,可用来帮助开发人员消除 java 的冗长代码,尤其是对于简单的 java 对象 (POJO)。它通过注释实现这一目的。
引入
IntelliJ 安装:

Lombok 是侵入性很高的一个 library。
maven 添加依赖:
1 | <dependency> |
注解说明
常用注解:

@Getter和@Setter
自动生成 getter 和 setter 方法。

@ToString
自动重写 toString() 方法,打印所有变量。也可以加其他参数,例如 @ToString(exclude=”id”) 排除 id 属性,或者 @ToString(callSuper=true, includeFieldNames=true) 调用父类的 toString() 方法,包含所有属性。

@EqualsAndHashCode
自动生成 equals(Object other) 和 hashcode() 方法,包括所有非静态变量和非 transient 的变量。

如果某些变量不想要加进判断,可以通过 exclude 排除,也可以使用 of 指定某些字段:

java 中规定,当两个 object equals 时,它们的 hashcode 一定要相同,反之,当 hashcode 相同时,object 不一定 equals。所以 equals 和 hashcode 要一起 implement,免得出现违反 java 规定的情形。
@NoArgsConstructor,@AllArgsConstructor,@RequiredArgsConstructor
这三个很像,都是自动生成该类的 constructor,差別只在生成的 constructor 的参数不一样而已。
@NoArgsConstructor:生成一个沒有参数的 constructor。

在 java 中,如果沒有指定类的 constructor,java compiler 会自动生成一个无参构造器,但是如果自己写了 constructor 之后,java 就不会再自动生成无参构造器。但是,很多时候,无参构造器是必须的,因此,为避免不必要的麻烦,应在类上至少加上
@NoArgsConstrcutor。
@AllArgsConstructor :生成一个包含所有参数的 constructor。

@RequiredArgsConstructor:生成一个包含 “特定参数” 的 constructor,特定参数指的是那些有加上 final 修饰词的变量。

如果所有的变量都沒有用 final 修饰,
@RequiredArgsConstructor会生成一个沒有参数的 constructor。
@Data
等于同时添加了以下注解:@Getter,@Setter,@ToString,@EqualsAndHashCode 和 @RequiredArgsConstructor。

@Value
把所有的变量都设成 final,其他的就跟 @Data 类似,等于同时添加了以下注解:@Getter,@ToString,@EqualsAndHashCode 和 @RequiredArgsConstructor。

- @Builder
自动生成流式 set 值写法。

注意,虽然只要加上 @Builder 注解,我们就能用流式写法快速设定 Object 的值,但是 setter 还是不应该舍弃的,因为 Spring 或是其他框架,有很多地方都会用到 Object 的 getter/setter 方法来对属性取值/赋值。
所以,通常是 @Data 和 @Builder 会一起用在同个类上,既方便流式写 code,也方便框架做事。比如:
1 |
|
@Slf4j
自动生成该类的 log 静态常量,要打日志就可以直接打,不用再手动 new log 静态常量了。

除了 @Slf4j 之外,Lombok 也提供其他日志框架的几种注解,像是 @Log,@Log4j 等,他们都可以创建一个静态常量 log,只是使用的 library 不一样而已。
1 | // 对应的log语句如下 |
更多的参考:https://juejin.cn/post/6844903557016076302
Logback
引入
1 | <dependency> |
logback 依赖中,含有对 slf4j 的依赖。
节点
configuration 为主节点,其主要字节点如下:
property
定义变量值的标签,有两个属性,name 和 value,定义变量后,可以使 “${name}” 来使用变量。
1 | <property name="logging.level" value="info"/> |
appender
日志打印的组件,定义打印过滤的条件、打印输出方式、滚动策略、编码方式、打印格式等。
种类:
ConsoleAppender:把日志添加到控制台。
1
2
3
4
5<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder charset="utf-8">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-6level %logger{50} - %msg%n</pattern>
</encoder>
</appender>FileAppender:把日志添加到文件。
1
2
3
4
5
6
7
8
9
10
11
12
13<appender name="ReactionExtractorAppender" class="ch.qos.logback.core.FileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>
${logging.path}/reaction-extractor.log
</file>
<encoder>
<pattern>${message.format}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>RollingFileAppender:FileAppender 的子类,滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14<appender name="ReactionExtractorRollingAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.path}/reaction-extractork-%d{yyyy-MM-dd}.log</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder>
<pattern>${message.format}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
属性:
name:指定 appender 的名称。
class:指定 appender 的全限定名。
子节点:
append:默认为 true,表示日志被追加到文件结尾,如果是 false,清空现存文件。
filter:过滤器,执行完一个过滤器后返回 DENY,NEUTRAL,ACCEPT 三个枚举值中的一个。
filter 的返回值含义:
- DENY:日志将立即被抛弃不再经过其他过滤器。
- NEUTRAL:有序列表里的下个过滤器过接着处理日志。
- ACCEPT:日志会被立即处理,不再经过剩余过滤器。
filter 的两种类型:
ThresholdFilter:临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回 NEUTRAL,当日志级别低于临界值时,日志会被拒绝。
1
2
3<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>LevelFilter:级别过滤器,根据日志级别进行过滤。如果日志级别等于配置级别,过滤器会根据 onMath (用于配置符合过滤条件的操作) 和 onMismatch (用于配置不符合过滤条件的操作) 接收或拒绝日志。
1
2
3
4
5<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
file:指定被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。
rollingPolicy:滚动策略,只有 appender 的 class 是 RollingFileAppender 时才需要配置。
TimeBasedRollingPolicy:根据时间来制定滚动策略,既负责滚动也负责触发滚动。
1
2
3
4
5
6
7
8<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件输出的文件名:按天回滚 daily -->
<FileNamePattern>
${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd HH:mm:ss.SSS}
</FileNamePattern>
<!-- 日志文件保留天数 -->
<MaxHistory>30</MaxHistory>
</rollingPolicy>每天生成一个日志文件,日志文件保存 30 天。
FixedWindowRollingPolicy:根据固定窗口算法重命名文件的滚动策略。
encoder:对记录事件进行格式化。主要作用是:把日志信息转换成字节数组,以及把字节数组写入到输出流。
1
2
3
4
5<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!-- 格式化输出:%d表示日期;%thread表示线程名;%-5level:级别从左显示5个字符宽度;%logger{50} 表示logger名字最长50个字符,否则按照句点分割;%msg:日志消息;%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
logger
用来设置某一个包或者具体的某一个类的日志打印级别以及指定 appender。
属性:
- name:指定受此 logger 约束的某一个包或者具体的某一个类。
- level:设置打印级别 (TRACE,DEBUG,INFO,WARN,ERROR,ALL 和 OFF),还有一个值 INHERITED 或者同义词 NULL,代表强制执行上级的级别。如果没有设置此属性,那么当前 logger 将会继承上级的级别。
- addtivity:设置是否向上级 logger 传递打印信息,默认为 true。
1 | <logger name="com.glmapper.spring.boot.controller" level="${logging.level}" additivity="false"> |
com.glmapper.spring.boot.controller 这个包下的 ${logging.level} 级别的日志将会使用 GLMAPPER-LOGGERONE 来打印。
root
根 logger,也是一种 logger,但只有一个 level 属性。
实例
1 | <!-- 使用说明: |
根据实际情况,对 appender 进行取舍,实际使用时不要所有的都添加到 logback.xml 配置文件中。
本文参考
https://kucw.github.io/blog/2020/3/java-lombok/
https://juejin.cn/post/6844903641535479821
声明:写作本文初衷是个人学习记录,鉴于本人学识有限,如有侵权或不当之处,请联系 wdshfut@163.com。