java框架之SpringBoot(3)-日志
市面上的日志框架
日志抽象层 | 日志实现 |
---|---|
JCL(Jakarta Commons Logging)、SLF4J(Simple Logging Facade For Java)、JBoss-Logging | Log4j、JUL(java.util.logging)、Log4j2、Logback |
日志抽象层
JBoss-Logging 不适合平常开发使用。JCL 最后一次更新版本时间为 2014 年,有些过时。所以 SpringBoot 选中的日志抽象层为 SLF4J。
日志实现
日志实现 LogBack、Log4j 和抽象层 SLF4J 的作者是同一个人,且 LogBack 是后期针对 Log4j 的升级版,而 Log4j2 是 Apache 旗下开发的日志框架。所以 SpringBoot 的日志实现使用的是 Logback。
SLF4J使用
编码
导入 slf4j 和 logback 的依赖,使用如下。
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
如何让系统中所有的日志都统一到 sfl4j?
- 将系统中其它日志框架排除。
- 用中间包替换原有的日志框架。
- 导入 sl4j 的其它实现。
SpringBoot日志关系
我们已经知道一个基本的 SpringBoot web 项目会包含如下依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
而在 spring-boot-starter-web 依赖又依赖于 spring-boot-stater , spring-boot-stater 就有日志相关依赖,如下:
总结:
- SpringBoot 底层也是使用 slf4j+logback 的方式进行日志记录。
- SpringBoot 使用中间包将其它的日志包都间接替换成了 slf4j,而 slf4j 的实现为 logback,所以 call 其它日志包 api 的时候实际上调用的是 logback,统一了日志实现。
- 如果我们要引入其它框架,一定要把这个框架的默认日志依赖排除。
SpringBoot日志使用
默认配置
日志级别
现有如下示例:
package com.springboot.logging; 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; @RunWith(SpringRunner.class) @SpringBootTest public class LoggingApplicationTests { @Test public void test() { Logger logger = LoggerFactory.getLogger(this.getClass()); // 如下日志级别由低到高 // 指定一个日志级别,就会在指定的级别之后的高级别生效 logger.trace("trace info"); logger.debug("debug info"); logger.info("info info"); logger.warn("warn info"); logger.error("error info"); } }
运行该测试代码,输出如下:
2018-03-16 17:08:34.913 INFO 16228 --- [ main] c.s.logging.LoggingApplicationTests : info info 2018-03-16 17:08:34.913 WARN 16228 --- [ main] c.s.logging.LoggingApplicationTests : warn info 2018-03-16 17:08:34.913 ERROR 16228 --- [ main] c.s.logging.LoggingApplicationTests : error info
得出结论,SpringBoot 程序中我们使用的日志输出默认是 info 级别。
我们可以通过配置文件修改指定包下的日志输出级别,例:
logging.level.com.springboot.logging=trace # 指定 com.springboot.logging 包下的日志输出级别为 trace
此时运行上面测试程序,输出内容为:
2018-03-16 17:13:06.451 TRACE 2836 --- [ main] c.s.logging.LoggingApplicationTests : trace info 2018-03-16 17:13:06.451 DEBUG 2836 --- [ main] c.s.logging.LoggingApplicationTests : debug info 2018-03-16 17:13:06.452 INFO 2836 --- [ main] c.s.logging.LoggingApplicationTests : info info 2018-03-16 17:13:06.452 WARN 2836 --- [ main] c.s.logging.LoggingApplicationTests : warn info 2018-03-16 17:13:06.452 ERROR 2836 --- [ main] c.s.logging.LoggingApplicationTests : error info
如果直接指定整个项目日志输出级别,那么只需要把包路径位置替换为 root ,如下:
logging.level.root=trace
输出到文件
日志不仅可输出到控制台,还可以配置输出到指定文件,如下:
logging.file=springboot.log
此时项目中的日志就会输出到项目根路径下的 springboot.log 文件中。
上面这种方式是使用相对项目路径,也可以使用完整的绝对路径,如下:
logging.file=D://springboot.log
也可以只指定日志存放目录:
logging.path=/springboot/log
此时就会在项目所在磁盘的根目录的 /springboot/log 文件夹下生成一个 spring.log 文件。
输出格式
我们可以改变日志的输出格式,比如在配置文件中修改在控制台的日志输出格式:
logging.path=/log # 控制台日志输出格式 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 # %d : 日期时间 # %thread : 线程名 # %-5level : 级别,从左显示 5 个字符宽度 # %logger{50} : logger 名称最长为 50 个字符,否则按照句点分割 # %msg : 日志消息 # %n : 换行符
此时运行上面测试程序,输出结果如下:
2019-03-16 17:41:23.432 [main] INFO com.springboot.logging.LoggingApplicationTests ---> Started LoggingApplicationTests in 2.355 seconds (JVM running for 3.052) 2019-03-16 17:41:23.486 [main] INFO com.springboot.logging.LoggingApplicationTests ---> info info 2019-03-16 17:41:23.486 [main] WARN com.springboot.logging.LoggingApplicationTests ---> warn info 2019-03-16 17:41:23.486 [main] ERROR com.springboot.logging.LoggingApplicationTests ---> error info
指定配置文件
要使用自定义的日志配置文件,只需要在类路径下放上对应日志框架自己的配置文件即可,SpringBoot 就不使用它的默认配置了。而对应日志框架的配置文件命名也是有限制的,如下:
日志框架 | 可使用配置文件名 |
---|---|
Logback | logback-spring.xml、logback-spring.groovy、logback.xml、logback.groovy |
log4j2 | log4j2-spring.xml、log4j2.xml |
JDK(Java Util Logging) | logging.properties |
我们此时使用的是 SpringBoot 默认使用的 logback,所以可以在类路径下放入“logback.xml”:
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="false"> <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径--> <property name="LOG_HOME" value="log"/> <!--定义日志文件名称--> <property name="FILE_NAME" value="testLog"/> <!-- 控制台输出 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!-- 格式化输出: %d 表示日期 %thread 表示线程名 %-5level 级别从左显示 5 个字符宽度 %msg 日志消息 %n 是换行符 --> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!-- 按照每天生成日志文件 --> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--日志文件输出的文件名--> <FileNamePattern>${LOG_HOME}/${FILE_NAME}.%d{yyyy-MM-dd}.log</FileNamePattern> <!--日志文件保留天数--> <MaxHistory>30</MaxHistory> </rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d 表示日期,%thread 表示线程名,%-5level 表示级别从左显示 5 个字符宽度 %msg 表示日志消息,%n 是换行符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> <!--日志文件最大的大小--> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <MaxFileSize>10MB</MaxFileSize> </triggeringPolicy> </appender> <!-- 日志输出级别 --> <root level="INFO"> <appender-ref ref="STDOUT"/> <!--启用控制台输出--> <appender-ref ref="FILE"/> <!--启用文件输出--> </root> </configuration>
此时“logback.xml”就可以直接被日志框架读取配置。
高级功能
在 SpringBoot 项目中,SpringBoot 是推荐我们使用文件名为“logback-spring.xml”的配置文件,因为使用“logback-spring.xml”文件名时该配置文件就不是直接被日志框架读取,而是先被 SpringBoot 读取,此时 SpringBoot 就给我们提供了日志框架以外的功能,可以定制不同 Profile 环境下来生效日志的不同配置,使用如下:
<root level="INFO"> <!--仅在非 prod 环境下启用控制台输出--> <springProfile name="!prod"> <appender-ref ref="STDOUT"/> <!--启用控制台输出--> </springProfile> <!--仅在 prod 环境下启用文件输出--> <springProfile name="prod"> <appender-ref ref="FILE"/> <!--启用文件输出--> </springProfile> </root>
切换日志框架
切换到log4j
SpringBoot 默认使用 logback 作为日志实现,而我们如果想要切换到其它日志实现该怎么做呢?下面以切换到 log4j 为例:
我们可以先分析 SpringBoot 的日志关系 和 SLF4J 的日志适配图:
因为默认使用的是 logback 实现,所以现在 SpringBoot 有导入 jcl-over-slf4j.jar 、 log4j-over-slf4j.jar 、 jul-to-slf4j.jar 这三个日志替换包,而我们要切换成 log4j 实现,首先我们要排除 log4j 的日志替换包即 log4j-over-slf4j.jar 和 logback 的实现包:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <artifactId>log4j-over-slf4j</artifactId> <groupId>org.slf4j</groupId> </exclusion> <exclusion> <artifactId>logback-classic</artifactId> <groupId>ch.qos.logback</groupId> </exclusion> </exclusions> </dependency>
接着看下图:
可以看到要将 log4j 切换为 slf4j 的实现需要两个替换包,这两个替换包 SpringBoot 默认已经使用了,所以还需要添加一个适配包:
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency>
此时可以添加 log4j 的配置文件“log4j.properties”:
log4j.rootLogger = info,stdout log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
运行项目,会发现日志实现已经切换到 log4j。
log4j2场景启动器
上面演示的是如何切换 SpringBoot 的日志实现为 log4j,看起来有些麻烦,下面再看一个示例,将 SpringBoot 的日志实现切换为 log4j2。
切换为 log4j2 就很简单了,因为 SpringBoot 给我们提供了 log4j2 的场景启动器,通过之前的分析我们已经知道 SpringBoot 默认日志场景启动器为 spring-boot-starter-logging ,下面我们直接排除这个场景启动器的依赖,添加 log4j2 的场景启动器:
<dependencies> <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> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
此时 SpringBoot 项目的日志实现就已经切换为 log4j2 了,同 logback,要使用 Profile 功能时,需修改 log4j2 的配置文件名为 log4j2-spring.xml 。
java框架之SpringBoot(3)-日志的更多相关文章
- 【java框架】SpringBoot(5)--SpringBoot整合分布式Dubbo+Zookeeper
1.理论概述 1.1.分布式 分布式系统是若干独立计算机的集合,这些计算机对于用户来讲就像单个系统. 由多个系统集成成一个整体,提供多个功能,组合成一个板块,用户在使用上看起来是一个服务.(比如淘宝网 ...
- java框架之SpringBoot(1)-入门
简介 Spring Boot 用来简化 Spring 应用开发,约定大于配置,去繁从简,just run 就能创建一个独立的.产品级别的应用. 背景: J2EE 笨重的开发.繁多的配置.低下的开发效率 ...
- java框架之SpringBoot(4)-资源映射&thymeleaf
资源映射 静态资源映射 查看 SpringMVC 的自动配置类,里面有一个配置静态资源映射的方法: @Override public void addResourceHandlers(Resource ...
- java框架之SpringBoot(5)-SpringMVC的自动配置
本篇文章内容详细可参考官方文档第 29 节. SpringMVC介绍 SpringBoot 非常适合 Web 应用程序开发.可以使用嵌入式 Tomcat,Jetty,Undertow 或 Netty ...
- java框架之SpringBoot(14)-任务
使用 maven 创建 SpringBoot 项目,引入 Web 场景启动器. 异步任务 1.编写异步服务类,注册到 IoC 容器: package zze.springboot.task.servi ...
- java框架之SpringBoot(15)-安全及整合SpringSecurity
SpringSecurity介绍 Spring Security 是针对 Spring 项目的安全框架,也是 Spring Boot 底层安全模块默认的技术选型.它可以实现强大的 Web 安全控制.对 ...
- java框架之SpringBoot(16)-分布式及整合Dubbo
前言 分布式应用 在分布式系统中,国内常用 Zookeeper + Dubbo 组合,而 SpringBoot 推荐使用 Spring 提供的分布式一站式解决方案 Spring + SpringBoo ...
- java框架之SpringBoot(2)-配置
规范 SpringBoot 使用一个全局的配置文件,配置文件名固定为 application.properties 或 application.yml .比如我们要配置程序启动使用的端口号,如下: s ...
- java框架之SpringBoot(6)-Restful风格的CRUD示例
准备 环境 IDE:Idea SpringBoot版本:1.5.19 UI:BootStrap 4 模板引擎:thymeleaf 3 效果:Restful 风格 CRUD 功能的 Demo 依赖 &l ...
随机推荐
- Navicat(数据库可视化操作软件)安装、配置、测试
Navicat(数据库可视化操作软件)安装.配置.测试(win7_64bit) 目录 1.概述 2.本文用到的工具 3.Navicat安装.激活与配置 4.简单测试 5.注意事项 6.相关博文 > ...
- Mysql获取最大自增ID(auto_increment)的五种方式及其特点
在关系型数据库的表结构中,一般情况下,都会定义一个具有‘AUTO_INCREMENT’扩展属性的‘ID’字段,以确保数据表的每一条记录都有一个唯一标识. 而实际应用中,获取到最近最大的ID值是必修课之 ...
- ubuntu下同时安装anaconda2与anaconda3,并分别安装与之对应的软件
1.安装anaconda2 参考网址:https://www.cnblogs.com/chamie/p/8876271.html 2.安装anaconda3 转载:https://blog.csdn. ...
- tensorflow冻结变量方法(tensorflow freeze variable)
最近由于项目需要,要对tensorflow构造的模型中部分变量冻结,然后继续训练,因此研究了一下tf中冻结变量的方法,目前找到三种,各有优缺点,记录如下: 1.名词解释 冻结变量,指的是在训练模型时, ...
- css如何实现一个元素高度固定宽度按比例显示?
用padding-top百分比可以实现宽度固定高度按比例展示,现在的需求是对一个video视频的盒子div高度是固定的,宽度如何按比例展示? 解决后效果如图: 红框标注的即是我在上面高度比例固定的范围 ...
- Git命令行大全
git branch 查看本地所有分支 git status 查看当前状态 git commit 提交 git branch -a 查看所有的分支 git branch -r 查看远程所有分支 git ...
- ganglia使用nagios告警
1.复制所需脚本到nagios的脚本目录,并设置权限 cp -fr ./ganglia-3.7.1/contrib/check_ganglia.py /usr/local/nagios/libe ...
- ubuntu16.04 在/etc/network/interfaces设置static ip无效
双网卡使用无线网卡上互联网,使用以太网卡连局域网,在/etc/network/interfaces里对以太网卡设置static ip无效,使用ifconfig临时设置也仅能工作一会,设置的ip马上就消 ...
- 前端编程tips
1.ts less 网上搜视频教程,不用太复杂的,短短几分钟视频基本就对其入门了,比自己搜官网学习更方便. 常用的ts技术:let name:string=""; let obj ...
- centos 7 IP不能访问nginx Failed connect to 185.239.226.111:80; No route to host解决办法
服务器环境 centos 7.4 问题描述 1.可以ping通IP ,用IP访问nginx 不能访问,在服务器上curl localhost curl 185.239.226.111可以获得 [ro ...