文章已经收录在 Github.com/niumoo/JavaNotes ,更有 Java 程序员所须要掌握的核心知识,欢迎Star和指教。
欢迎关注个人 公众号,文章每周更新。注意:本 Spring Boot 系列文章基于 Spring Boot 版本 v2.1.1.RELEASE 进行学习分析,版本不一样可能会有细微差异。html
Spring 框架选择使用了 JCL 做为默认日志输出。而 Spring Boot 默认选择了 SLF4J 结合 LogBack。那咱们在项目中该使用哪一种日志框架呢?在对于不一样的第三方 jar 使用了不一样的日志框架的时候,咱们该怎么处理呢?
<!-- more -->java
日志对于应用程序的重要性不言而喻,不论是记录运行状况仍是追踪线上问题,都离不开对日志的分析,在 Java 领域里存在着多种日志框架,如 JUL, Log4j, Log4j2, Commons Loggin, Slf4j, Logback 等。关于 Log4j, Log4j2 和 Slf4j 直接的故事这里不作介绍,有兴趣能够自行百度。git
在开发的时候不该该直接使用日志实现类,应该使用日志的抽象层。具体参考 SLF4J 官方。
下图是 SLF4J 结合各类日志框架的官方示例,从图中能够清晰的看出 SLF4J API 永远做为日志的门面,直接应用与应用程序中。程序员
同时 SLF4 官方给出了简单示例。github
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HelloWorld { public static void main(String[] args) { Logger logger = LoggerFactory.getLogger(HelloWorld.class); logger.info("Hello World"); } }
须要注意的是,要为系统导入 SLF4J 的 jar 和 日志框架的实现 jar. 因为每个日志的实现框架都有本身的配置文件,因此在使用 SLF4 以后,配置文件仍是要使用实现日志框架的配置文件。web
通常状况下,在项目中存在着各类不一样的第三方 jar ,且它们的日志选择也可能不尽相同,显然这样是不利于咱们使用的,那么若是咱们想为项目设置统一的日志框架该怎么办呢?面试
在 SLF4J 官方,也给了咱们参考的例子。spring
从图中咱们获得一种统一日志框架使用的方式,可使用一种和要替换的日志框架类彻底同样的 jar 进行替换,这样不至于原来的第三方 jar 报错,而这个替换的 jar 其实使用了 SLF4J API. 这样项目中的日志就均可以经过 SLF4J API 结合本身选择的框架进行日志输出。
统一日志框架使用步骤概括以下:shell
根据上面总结的要统一日志框架的使用,第一步要排除其余的日志框架,在 Spring Boot 的 Maven 依赖里能够清楚的看到 Spring Boot 排除了其余日志框架。咱们自行排除依赖时也只须要按照图中的方式就行了。apache
其实 Spring Boot 也是使用了 SLF4J+logback 的日志框架组合,查看 Spring Boot 项目的 Maven 依赖关系能够看到 Spring Boot 的核心启动器 spring-boot-starter 引入了 spring-boot-starter-logging.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> <version>2.1.1.RELEASE</version> <scope>compile</scope> </dependency>
而 spring-boot-starter-logging 的 Maven 依赖主要引入了 logback-classic (包含了日志框架 Logback 的实现),log4j-to-slf4j (在 log4j 日志框架做者开发此框架的时候尚未想到使用日志抽象层进行开发,所以出现了 log4j 向 slf4j 转换的工具),jul-to-slf4j ( Java 自带的日志框架转换为 slf4j).
<dependencies> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-to-slf4j</artifactId> <version>2.11.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>1.7.25</version> <scope>compile</scope> </dependency> </dependencies>
从上面的分析,Spring Boot 对日志框架的使用已是清晰明了了,咱们使用 IDEA 工具查看 Maven 依赖关系,能够清晰的看到日志框架的引用。若是没有 IDEA 工具,也可使用 Maven 命令查看依赖关系。
mvn dependency:tree
因而可知,Spring Boot 能够自动的适配日志框架,并且底层使用 SLF4 + LogBack 记录日志,若是咱们自行引入其余框架,须要排除其日志框架。
从上面的分析,发现 Spring Boot 默认已经使用了 SLF4J + LogBack . 因此咱们在不进行任何额外操做的状况下就可使用 SLF4J + Logback 进行日志输出。
编写 Java 测试类进行测试。
import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; /** * <p> * 测试日志输出, * SLF4J 日志级别从小到大trace,debug,info,warn,error * * @Author niujinpeng * @Date 2018/12/11 21:12 */ @RunWith(SpringRunner.class) @SpringBootTest public class LogbackTest { Logger logger = LoggerFactory.getLogger(getClass()); @Test public void testLog() { logger.trace("Trace 日志..."); logger.debug("Debug 日志..."); logger.info("Info 日志..."); logger.warn("Warn 日志..."); logger.error("Error 日志..."); } }
已知日志级别从小到大为 trace < debug < info < warn < error . 运行获得输出以下。因而可知 Spring Boot 默认日志级别为 INFO.
2018-12-11 23:02:58.028 [main] INFO n.c.boot.LogbackTest - Info 日志... 2018-12-11 23:02:58.029 [main] WARN n.c.boot.LogbackTest - Warn 日志... 2018-12-11 23:02:58.029 [main] ERROR n.c.boot.LogbackTest - Error 日志...
从上面的日志结合 Logback 日志格式能够知道 Spring Boot 默认日志格式是。
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n # %d{yyyy-MM-dd HH:mm:ss.SSS} 时间 # %thread 线程名称 # %-5level 日志级别从左显示5个字符宽度 # %logger{50} 类名 # %msg%n 日志信息加换行
至于为何 Spring Boot 的默认日志输出格式是这样?咱们能够在 Spring Boot 的源码里找到答案。
能够直接在配置文件编写日志相关配置。
# 日志配置 # 指定具体包的日志级别 logging.level.net.codingme=debug # 控制台和日志文件输出格式 logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n # 日志文件大小 logging.file.max-size=10MB # 保留的日志时间 logging.file.max-history=10 # 日志输出路径,默认文件spring.log logging.path=systemlog #logging.file=log.log
关于日志的输出路径,可使用 logging.file 或者 logging.path 进行定义,二者存在关系以下表。
logging.file |
logging.path |
例子 | 描述 |
---|---|---|---|
(没有) | (没有) | 仅控制台记录。 | |
具体文件 | (没有) | my.log |
写入指定的日志文件,名称能够是精确位置或相对于当前目录。 |
(没有) | 具体目录 | /var/log |
写入spring.log 指定的目录,名称能够是精确位置或相对于当前目录。 |
由于 Log4j 日志框架已经年久失修,原做者都以为写的很差,因此下面演示替换日志框架为 Log4j2 的方式。根据官网咱们 Log4j2 与 logging 须要二选一,所以修改 pom以下。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <artifactId>spring-boot-starter-logging</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency>
文章代码已经上传到 GitHub Spring Boot 日志系统。
最后的话
文章已经收录在 Github.com/niumoo/JavaNotes ,欢迎Star和指教。更有一线大厂面试点,Java程序员须要掌握的核心知识等文章,也整理了不少个人文字,欢迎 Star 和完善,但愿咱们一块儿变得优秀。
文章有帮助能够点个「赞」或「分享」,都是支持,我都喜欢!
文章每周持续更新,要实时关注我更新的文章以及分享的干货,能够关注「 未读代码 」公众号或者个人博客。