本篇在jdk21下测试通过
2.⽇志实现
在JDK 1.3及以前,Java打⽇志依赖System.out.println(), System.err.println()或者
e.printStackTrace(),Debug⽇志被写到STDOUT流,错误⽇志被写到STDERR流。这样打⽇志有⼀个⾮常⼤的缺陷,⾮常机械,⽆法定制,且⽇志粒度不够细分
System.out.println("123");
System.err.println("456");
注意了:这里案例采用的是log4j2的写法
2001年发布了Log4j,并将其捐献给了Apache软件基⾦会,成为Apache 基⾦会的顶级项⽬。Log4j 在设计上⾮常优秀,它定义的Logger、Appender、Level等概念对后续的 Java Log 框架有深远的影响,如今的很多⽇志框架基本沿⽤了这种思想
1.导入坐标
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-apiartifactId>
<version>2.22.1version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>2.22.1version>
dependency>
2.编写配置文件 log4j2.xml
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
Console>
<File name="MyFile" fileName="logs/app.log">
<PatternLayout>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %c{1} - %msg%npattern>
PatternLayout>
File>
Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
<AppenderRef ref="MyFile"/>
Root>
Loggers>
Configuration>
3.测试类
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class MyLog4j {
private static final Logger logger = LogManager.getLogger(MyLog4j.class);
public static void main(String[] args) {
int i = 1;
String msg = "测试";
String s = null;
// 记录不同级别的日志
logger.debug("Debug message:{},{},{}", i, msg, s);
logger.info("Info message:{},{},{}", i, msg, s);
logger.warn("Warning message:{},{},{}", i, msg, s);
logger.error("Error message:{},{},{}", i, msg, s);
logger.fatal("Fatal error message:{},{},{}", i, msg, s);
}
}
sun公司对于log4j的出现内⼼隐隐表示嫉妒。于是在jdk1.4版本后,开始搞事情,增加了⼀个包为java.util.logging,简称为JUL,⽤以对抗log4j ,但是却给开发造成了麻烦。相互引⽤的项⽬之间可能使⽤了不同的⽇志框架,经常将代码搞得⼀⽚混乱
import java.util.logging.Logger;
public class MyJul {
static Logger logger = Logger.getLogger(MyJul.class.getName());
public static void main(String[] args) {
int i = 1;
String msg = "测试";
String s = null;
logger.info( "Info message :" + i + " " + "s" + " " + msg);
}
}
从上⾯可以看出,JUL的api与log4j是完全不同的(参数只接受String)。由于⽇志系统互相没有关联,彼此没有约定,不同⼈的代码使⽤不同⽇志,替换和统⼀也就变成了⽐较棘⼿的⼀件事。假如你的应⽤使⽤log4j,然后项⽬引⽤了⼀个其他团队的库,他们使⽤了JUL,你的应⽤就得使⽤两个⽇志系统了,然后其他团队⼜使⽤了simplelog……这个时候如果要调整⽇志的输出级别,⽤于跟踪某个信息,简直就是⼀场灾难
那这个状况该如何解决呢?答案就是进⾏抽象,抽象出⼀个接⼝层,对每个⽇志实现都适配或者转接,这样这些提供给别⼈的库都直接使⽤抽象层即可 ,以后调⽤的时候,就调⽤这些接⼝。(⾯向接⼝思想)
于是,JCL(Jakarta Commons Logging)应运⽽⽣,也就是commons-logging-xx.jar组件。JCL 只提供 log 接⼝,具体的实现则在运⾏时动态寻找。这样⼀来组件开发者只需要针对 JCL 接⼝开发,⽽调⽤组件的应⽤程序则可以在运⾏时搭配⾃⼰喜好的⽇志实践⼯具
1.导入坐标
<dependency>
<groupId>commons-logginggroupId>
<artifactId>commons-loggingartifactId>
<version>1.3.0version>
dependency>
2.测试代码
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class MyJul {
private static Log logger = LogFactory.getLog(MyJul.class);
public static void main(String[] args) {
int i = 1;
String msg = "测试";
String s = null;
logger.info( "Info message :" + i + " " + "s" + " " + msg);
logger.debug("Debug message :" + i + " " + "s" + " " + msg);
logger.fatal("Fatal message :" + i + " " + "s" + " " + msg);
logger.error("Error message :" + i + " " + "s" + " " + msg);
}
}
针对以上情况,log4j的作者再次出⼿,他觉得JCL不好⽤,⾃⼰⼜写了⼀个新的接⼝api,就是slf4j,并且为了追求更极致的性能,新增了⼀套⽇志的实现,就是logback,⼀时间烽烟⼜起……
1.导入坐标
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>2.0.10version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-coreartifactId>
<version>1.4.14version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>1.4.14version>
dependency>
2.编写配置文件logback.xml
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{96} [%line] [%thread]- %msg%npattern>
encoder>
appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.logfile>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.logfileNamePattern>
<maxHistory>30maxHistory>
rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%npattern>
encoder>
appender>
<root level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
root>
configuration>
3.测试代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyLogback {
static final Logger logger = LoggerFactory.getLogger(MyLogback.class);
public static void main(String[] args) {
int i = 1;
String msg = "测试";
String s = null;
// 记录不同级别的日志
logger.debug("Debug message:{}:{}:{}", i, msg, s);
logger.info("Info message:{}:{}:{}", i, msg, s);
logger.warn("Warning message:{},{},{}", i, msg, s);
logger.error("Error message:{}:{}:{}", i, msg, s);
}
}
请参考 “开创先驱的log4j” 的写法
log4j2以性能著称,它⽐其前身Log4j 1.x提供了重⼤改进,同时类⽐logback,它提供了Logback中可⽤的许多改进,同时修复了Logback架构中的⼀些固有问题。功能上,它有着和Logback相同的基本操作,同时⼜有⾃⼰独特的部分,⽐如:插件式结构、配置⽂件优化、异步⽇志等
到log4j2,轰轰烈烈的java log战役基本就结束了