Springboot 系列(四)Spring Boot 日志框架
文章已经收录在 Github.com/niumoo/JavaNotes ,更有 Java 程序员所需要掌握的核心知识,欢迎Star和指教。
欢迎关注我的公众号,文章每周更新。、
注意:本 Spring Boot 系列文章基于 Spring Boot 版本 v2.1.1.RELEASE 进行学习分析,版本不同可能会有细微差别。
前言
Spring 框架选择使用了 JCL 作为默认日志输出。而 Spring Boot 默认选择了 SLF4J 结合 LogBack。那我们在项目中该使用哪种日志框架呢?在对于不同的第三方 jar 使用了不同的日志框架的时候,我们该怎么处理呢?
<!-- more -->
1. 日志框架介绍
日志对于应用程序的重要性不言而喻,不管是记录运行情况还是追踪线上问题,都离不开对日志的分析,在 Java 领域里存在着多种日志框架,如 JUL, Log4j, Log4j2, Commons Loggin, Slf4j, Logback 等。关于 Log4j, Log4j2 和 Slf4j 直接的故事这里不做介绍,有兴趣可以自行百度。
2. SLF4 的使用
在开发的时候不应该直接使用日志实现类,应该使用日志的抽象层。具体参考 SLF4J 官方。 下图是 SLF4J 结合各种日志框架的官方示例,从图中可以清晰的看出 SLF4J API 永远作为日志的门面,直接应用与应用程序中。
同时 SLF4 官方给出了简单示例。
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 之后,配置文件还是要使用实现日志框架的配置文件。
3. 统一日志框架的使用
一般情况下,在项目中存在着各种不同的第三方 jar ,且它们的日志选择也可能不尽相同,显然这样是不利于我们使用的,那么如果我们想为项目设置统一的日志框架该怎么办呢?
在 SLF4J 官方,也给了我们参考的例子。
从图中我们得到一种统一日志框架使用的方式,可以使用一种和要替换的日志框架类完全一样的 jar 进行替换,这样不至于原来的第三方 jar 报错,而这个替换的 jar 其实使用了 SLF4J API. 这样项目中的日志就都可以通过 SLF4J API 结合自己选择的框架进行日志输出。 统一日志框架使用步骤归纳如下:
- 排除系统中的其他日志框架。
- 使用中间包替换要替换的日志框架。
- 导入我们选择的 SLF4J 实现。
4. Spring Boot 的日志关系
4.1. 排除其他日志框架
根据上面总结的要统一日志框架的使用,第一步要排除其他的日志框架,在 Spring Boot 的 Maven 依赖里可以清楚的看到 Spring Boot 排除了其他日志框架。 我们自行排除依赖时也只需要按照图中的方式就好了。
4.2. 统一框架引入替换包
其实 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 记录日志,如果我们自行引入其他框架,需要排除其日志框架。
5. Spring Boot 的日志使用
5.1. 日志级别和格式
从上面的分析,发现 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 的源码里找到答案。
5.2 自定义日志输出
可以直接在配置文件编写日志相关配置。
# 日志配置 # 指定具体包的日志级别 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 指定的目录,名称可以是精确位置或相对于当前目录。 |
6. 替换日志框架
因为 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 和完善,希望我们一起变得优秀。
文章有帮助可以点个「赞」或「分享」,都是支持,我都喜欢!
文章每周持续更新,要实时关注我更新的文章以及分享的干货,可以关注「 未读代码 」公众号或者我的博客。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Spring 属性自动注入的基本流程
下面是最普通的Bean注入流程 ,@AutoWire属性方式 从 AnnotationConfigApplicationContext() 构造方法开始 在这个构造方法中调用 父类 AbstractApplicationContext 的 refresh()方法 refresh()方法中调用 本类中的 finishBeanFactoryInitialization(ConfigurableListableBeanFactory)方法,这个方法的参数是在AnnotationConfigApplicationContext()对象初始化时 new 出来的 finishBeanFactoryInitialization方法中调用 beanFactory.preInstantiateSingletons(); preInstantiateSingletons 方法中会遍历它已经得到的所有beanDefinition的名字,beanDefinition的名字是在调用refresh()方法之前 扫描包路径中的类等到的,这里可以看spring的包扫描器ClassPathBeanDefinitionS...
- 下一篇
从一年前的1200多人优化到现在200多人,待在这样的技术团队是一种什么体验?
1.写点情怀 平日里都是分享技术的,但是最近做的最多的一件事却是送别,挺悲伤的一个词,我个人不太喜欢,但是现在整个大的环境都不太景气,众多企业纷纷倒闭,一批批工人,白领被迫失去了工作,其中也不乏我自己所在的职业:程序员。特别的从去年年底至今,依旧活着的公司大部分也是苟延残喘,大幅度的“优化”员工,而我自己身边的朋友,送走了一批又一批,自己的感触挺深的,所以想把这段时间的经历写成文字,当做是解压了。 2.亲身经历 在现在这家公司干了接近三年了,刚进来时,整个IT部分是700多人,当时业务发展速度很快,很多业务线需要技术做数据支撑,那时公司处在上升期,所以不断的在扩张技术团队去满足各种业务需求,顶峰时期,技术团队达到了1200多人,各种项目也是琳琅满目(姑且这样形容吧,算是对好的一种向往),自己也有参与到不同的项目中,也学到了挺多东西,交到了很多朋友,乐此不疲。但是好景不长,伴随着互联网寒冬以及疫情的到来,从去年年底到现在,身边很多朋友陆陆续续都离开了,举一个印象比较深刻的例子: 去年五月份开始,我们领导找我组建一个新的项目团队,做3D应用相关的开发,当时结合了公司的业务和市场反馈,经过简...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Hadoop3单机部署,实现最简伪集群
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果