购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.3 Spring Boot日志

1.3.1 日志框架介绍

在系统开发中,日志是很重要的一个环节。日志写得好对于我们开发调试、线上问题追踪等都有很大的帮助。但使用日志并不是简单的输出信息,需要考虑很多问题,比如日志输出的速度、日志输出对于系统内存、CPU的影响等,为此出现了很多日志框架,以帮助开发者解决日志系统面临的这些问题。

比较常用的日志有Log4j、SLF4J、commons-logging、logback。当然,JDK本身也提供了java.util.logging包来提供对日志的支持,下面是常见的日志框架。

(1)commons-ogging:是Apache最早提供的日志门面接口。它的主要作用是提供一个日志门面,这样用户就可以使用不同的日志。用户可以自由选择第三方的日志组件,像Log4j,或者JDK自带的logging。common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库。common-logging内部有一个Simple logger的简单实现,但是功能很弱。

(2)SLF4J:是Simple Logging Facade for Java的简称,即Java的简单日志门面。类似于Apache common-logging,是对不同日志框架提供的一个门面封装,在部署的时候不修改任何配置即可接入一种日志实现方案。但是,它需要在编译时静态绑定真正的Log库。使用SLF4J时,如果需要使用某一种日志的具体实现,那么我们必须选择正确的SLF4J的jar包的集合(各种桥接包)。

(3)Log4j:经典的一种日志实现方案,也是Apache的一个开放源码项目。Log4j内部把日志系统抽象并封装成logger、appender、pattern等实现。我们可以通过配置文件轻松地实现日志系统的管理和多样化配置。通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等。用户也可以控制每一条日志的输出格式,通过定义每一条日志信息的级别,用户能够更加精细地控制日志的生成过程。这些都可以通过一个配置文件来灵活地进行配置,而不需要修改程序代码。

(4)logback:也是一种日志的实现方案。logback是由Log4j创始人设计的又一个开源日志组件。logback分成三个模块:logback-core、logback-classic和logback-access。logback-core是其他两个模块的基础模块。logback-classic是Log4j的一个改良版本。此外,logback-classic完整实现了SLF4J API,使我们可以很方便地更换成其他日志系统,如Log4j或JDK14Logging。logback-access访问模块可以与Servlet容器集成,提供了通过HTTP来访问日志的功能。

各个框架之间的关系

对于上述的日志框架,在开发过程中我们更多关注的是它们各自的用法,尤其是它们之间的搭配组合,所以必须理清它们之间的关系:

(1)commons-logging和SLF4J是Java中的日志门面,它们提供了一套通用的接口,具体的实现可以由开发者自由选择。Log4j和logback则是具体的日志实现方案。

(2)它们可以理解为接口与实现类的关系。

(3)四个框架都可以在程序中使用,但是为了考虑扩展性,一般在程序开发时,我们会选择使用commons-logging或者SLF4J这些日志门面,而不是直接使用Log4j或者logback这些实现方案。也就是说,我们编写代码时导入的类一般都是来自门面框架中的类,然后将某个日志的实现框架加入到项目中,以提供真正的日志输出功能。

(4)比较常用的搭配是commons-logging+Log4j或者SLF4J+logback。

Spring Boot框架选用的是SLF4J和logback。

1.3.2 SLF4J的使用

1.如何在系统中使用SLF4J

在开发的时候,对于日志记录方法的调用,不应该直接调用日志的实现类,而是调用日志抽象层里面的方法。

首先把SLF4J的jar和logback的实现jar导入到系统中,在类中的具体使用方式如下:

每一个日志的实现框架都有自己的配置文件。使用SLF4J以后,配置文件还是编写成日志实现框架自身的配置文件,如Log4j有自己的默认配置文件。

2.统一项目日志记录

在我们日常开发使用的框架中,往往都会引入一个日志框架来辅助输出框架信息。然而框架之间由于历史迭代的原因以及框架性能等问题,选择的日志框架也不一样,常见的框架与默认选择的日志系统关系如下:Spring(commons-logging)、Hibernate(jboss-logging)、MyBatis等。

开发常用的框架,如Spring、MyBatis等使用的框架都是框架开发者自己选择的。如果我们每开发一个框架就引入一个日志系统,最终需要打印日志的时候,就会出现使用n种日志系统的平台,并且每一种的日志打印的格式、内容和性能都需要手动去控制,这样不仅让项目变大,而且增加了项目的复杂度,对性能也有很大的影响。

官方建议的方案是,针对不同的日志框架,开发一套适配兼容的框架与之对应,使用这些兼容jar来替代原来的日志框架即可,例如Log4j日志框架,与之对应的就是log4j-over-slf4j.jar。对于常见的日志框架,SLF4J团队实现了一套与之对应的基于SLF4J的兼容框架,在使用Spring Boot的时候,我们会发现官方默认使用spring-boot-starter-logging这个Starter来引入日志系统,图1-4为展开的该依赖的依赖图。

图1-4

可以看到spring‐boot‐starter‐logging这个Starter中,引入了四个日志实例的依赖,分别是logback和我们前面提到的日志兼容jar的依赖,并且最终引入了SLF4J的日志门面的依赖,以实现统一的日志处理。这里,为什么引入了兼容的jar就能解决日志输出的问题呢,下面展开其中几个兼容的jar包,如图1-5所示。

图1-5

原来这些日志兼容包的包名与原来的日志框架的包名完全一样,并且完全按照SLF4J的方式实现了一套和以前一样的API。因此,依赖这些日志框架的开源框架在运行的时候查找对应包名下的class也不会报错,但熟悉Java类加载机制的开发人员都知道,两个jar的包名以及使用的class都一样的话,加载会出现异常,我们进入spring‐boot‐starter‐logging的pom依赖中一探究竟,最后在Maven依赖中发现了端倪,Spring框架使用的是commons-logging,而在spring-boot-starter-logging中已经将Spring的日志依赖排除掉了,如下:

这样Spring框架在运行时使用的就是兼容jar的日志实例了。

总的来说,在Spring Boot项目中要做到统一日志记录,需要按照以下步骤:

(1)将系统中其他日志框架先排除出去。

(2)用中间包来替换原有的日志框架。

(3)导入SLF4J其他的实现。

1.3.3 Spring Boot中日志的使用

本节对应的示例代码在本章案例源码文件夹下,项目名称是spring-boot-03-logging。

1.默认配置

Spring Boot默认帮我们配置好了日志,使用方式如下:

//记录器
Logger logger = LoggerFactory.getLogger(getClass());
@Test
public void contextLoads() {
    //System.out.println();
    //日志的级别
    //由低到高 trace<debug<info<warn<error
    //可以调整输出的日志级别;之后在这个日志级别或更高的日志级别才会生效
    logger.trace("这是trace日志...");
    logger.debug("这是debug日志...");
    //SpringBoot默认使用的是info级别的日志,没有指定级别的就用Spring Boot默认规定的日
志级别;root级别
    logger.info("这是info日志...");
    logger.warn("这是warn日志...");
    logger.error("这是error日志...");          }

日志输出格式:

· %d:表示日期时间。

· %thread:表示线程名。

· %-5level:从左边开始用5个字符宽度显示日志级别。

· %logger{50}:表示logger名字最长50个字符,否则按照句点分割。

· %msg:日志消息。

· %n:换行符。

Spring Boot可以修改日志的默认配置、日志文件的指定路径、打印日志格式、日志级别等,具体如下:

示例代码1-13 application .properties

logging.level.com.spring=trace
#logging.path=
# 不指定路径时,就在当前项目下生成springboot.log日志
# 可以指定完整的路径
#logging.file=G:/springboot.log
# 在当前磁盘的根路径下创建spring文件夹及其下面的log子文件夹;使用 spring.log 作为默认文件
logging.path=/spring/
#  在控制台输出日志的格式
logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
# 指定文件中日志输出的格式
logging.pattern.file=%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50}
==== %msg%n

2.指定配置

可以不使用Spring Boot默认的日志配置,改用所选日志框架自己的配置文件。只需要在类路径下存放好每个日志框架自己的配置文件,Spring Boot就不再使用自己默认的配置了。不同日志框架的配置文件命名如表1-2所示。

表1-2 不同日志框架对应配置文件的文件名

logback.xml:日志框架默认识别该文件。

logback-spring.xml:日志框架不直接加载日志的配置项,由Spring Boot解析日志配置,可以使用Spring Boot的高级profile功能。

如:

如果使用logback.xml作为日志配置文件,还要使用profile功能,否则会提示以下错误:no applicable action for [springProfile]。

1.3.4 切换日志框架

根据1.3.2小节所讲的内容,Spring Boot选用SLF4J和logback,其中SLF4J作为日志门面,logback作为日志实现,可以按照SLF4J的日志适配图进行相关的切换。企业开发中可供使用的日志实现框架很多,这里建议大家选用Log4j2。Log4j2已经不仅仅是Log4j的一个升级版本了,它从头到尾都被重写了,相比于其他的日志系统,Log4j2丢数据这种情况很少发生;它使用了disruptor技术,在多线程环境下,性能比logback高10倍以上;它利用JDK 1.5并发的特性,减少了死锁的发生。下面看一下整合步骤:

(1)Spring Boot默认采用logback的日志框架,所以需要排除logback,不然会出现jar依赖冲突的错误。

示例代码1-14 pom.xml(文件的部分代码)

(2)如果自定义了日志配置文件名,需要在application.properties中进行设置:

logging.config=classpath:log4j2.xml

配置文件默认名称如果是log4j2-spring.xml,则可以不在application.yml中进行设置。

(3)日志配置文件模板。

Log4j通过一个.properties的文件作为主配置文件,而现在的Log4j2则已经弃用了这种方式,采用的是.xml、.json或者.jsn这种方式来做配置文件,这也是技术发展的必然性,因为properties文件的可阅读性不太好。这里给出一个.xml格式的参考模板,大家可以参考来写。

配置模板文件中部分参数解释如下:

(1)根节点Configuration,有两个属性,分别是status和monitorinterval:

· Status:用来指定Log4j本身的打印日志的级别。

· Monitorinterval:用于指定Log4j自动重新配置的监测间隔时间,单位是s,最小是5s。

(2)有两个子节点:Appenders和Loggers(表明可以定义多个Appender和Logger)。Appenders节点常见的有三个子节点:Console、RollingFile、File。

· Console节点:用来定义输出到控制台的Appender,其属性有:

name:指定Appender的名字。

target:SYSTEM_OUT或SYSTEM_ERR,一般只设置默认值SYSTEM_OUT。

PatternLayout:输出格式,不设置则默认为%m%n。

· File节点:用来定义输出到指定位置的文件的Appender。属性有:

name:指定Appender的名字。

fileName:指定输出日志的目的文件带全路径的文件名。

PatternLayout:输出格式,不设置则默认为%m%n。

· RollingFile节点:用来定义超过指定条件自动删除旧的创建新的Appender,属性有:

name:指定Appender的名字。

fileName:指定输出日志的目的文件带全路径的文件名。

PatternLayout:输出格式,不设置则默认为%m%n。

filePattern:指定当发生Rolling时,文件的转移和重命名规则。

(3)Loggers节点,常见的有两种:Root和Logger。

· Root节点:用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出。

level:日志输出级别,共有8个级别,按照从低到高排列为:All < Trace < Debug < Info< Warn < Error < Appender。

Ref:Root的子节点,用来指定该日志输出到哪个Appender。

· Logger节点:用来单独指定日志的形式,比如,为指定包下的class指定不同的日志级别。

AppenderRef:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root;如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity="false",只在自定义的Appender中进行输出。

本节案例中的log4j2.xml代码如下所示:

示例代码1-15 log4j2.xml

(4)Log4j2框架的使用方式。

与其他日志框架使用方式差不多,简单的使用方式如下: hp1JltkaYsqpswjebtuDK51fgbpPSdUi/Ddp1sj3KIhPiBGOz/RTr67z/MTv6QuL

private static final org.slf4j.Logger log =
org.slf4j.LoggerFactory.getLogger(LogExampleOther.class);
  public static void main(String... args) {
    log.error("Something else is wrong here");
  }
点击中间区域
呼出菜单
上一章
目录
下一章
×