log4j2研究之配置文件模块化

x33g5p2x  于2021-12-25 转载在 其他  
字(3.0k)|赞(0)|评价(0)|浏览(323)

模块化作为软件开发领域里的重要思想之一,我们在实际的工作中处处都能看到其身影。本文将尝试将这种思路应用到log4j2的配置文件中。

1. 概述

在软件开发领域,日志总是非常基础且重要的一环。log4j2作为Java领域里日志框架的佼佼者,后发优势使其迅速获得众多开发者的青睐。

XML配置作为log4j2官方的首推配置方式,被绝大多数开发人员所熟知。但XML语言天然的繁琐啰嗦的语法格式,以及具体业务场景下对日志的精密划分,势必导致我们的log4j2.xml 这个配置文件变得非常臃肿、庞大;于是一个改良思路顺理成章地出现了:我们是否可以将这个文件拆分成多个配置文件,最后再将这些配置文件组装成为一个完整的配置?答案当然是肯定的,接下来笔者就介绍实现这种想法的两种思路。

2. XInclude实现

这种实现方式其实和log4j2本身没有太大的关系,这个属于XML自带的一种模块化思路,具体的可以参见笔者在下面给出的链接。这里就不作过多的纠结,具体的实现方式在官方文档里也已经给出了,读者可以自行查阅(相应的官方文档地址笔者在下面也已给出)。

这里还是给出一些笔者在实际运用过程中遇到的一些注意事项:

  1. <xi:include /> 节点的放置位置很重要。对于include节点导入的内容, 有先后顺序之别。
  2. 如果 <properties> 想要覆盖 log4j2-xinclude-properties.xml 中定义的属性, 则需要保证 <properties> 在先,而在后。
  3. log4j2-xinclude-appenders.xml 中如果用到了 log4j2-xinclude-properties.xml 中配置的属性,则必须 log4j2-xinclude-properties.xml 在先。
  4. 节点之间的覆盖是整体覆盖,例如下面样例中的 <properties> , 属于 <properties> 节点覆盖,而不是里面单个 <property> 的重复覆盖。而且xinclude文件中定义时,必须是顶级节点(即Appenders/Loggers/Properties等。)
  5. 之前所谈到的覆盖都是 先到者优先,即保留排名在前的配置项。
  6. 样例XML如下:
<!--主体log4j2.xml配置文件-->
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error" xmlns:xi="http://www.w3.org/2001/XInclude">
    <!-- this will override the log pattern defined in the included log4j-properties.xml -->
    <!--这里定义的Properties将覆盖log4j2-xinclude-properties.xml定义的内容, 注意是全部覆盖, 不仅仅是log-pattern属性. 即使log4j2-xinclude-properties.xml中的Properties也许拥有更多的配置项。-->
    <Properties>
        <Property name="log-pattern">jit %d %-5p [%t] %C{1.} - %m%n</Property>
    </Properties>

    <xi:include href="log4j2-xinclude-properties.xml" />
    <xi:include href="log4j2-xinclude-appenders.xml" />
</Configuration>

<!-- log4j2-xinclude-properties.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<Properties>
    <!-- define the log pattern as a property so that it can be overridden -->
    <Property name="log-pattern">%d %-5p [%t] %C{1.} - %m%n</Property>
</Properties>

注意

  • 这种方式之下,应用所部署的路径中不能包含有中文。

3. Composite Configuration实现

笔者在查找上一种解决方案的过程中,偶然在官网上看到了另外一种实现思路,也就是LOG4J2中论述的Composite Configuration(这里也可以看出LOG4J2的后发优势真是相当巨大,开发人员吸取了大量之前LOG框架的教训并将之在log4j2中进行了解决)。

官方文档里并没有给出相应的示例,笔者结合官方给出的文档,再经过一番源码追踪后,大致实现了一个可运行的版本。

  1. 首先你需要配置一个名为log4j.configurationFile的配置项(关于这个配置项,你可以在ConfigurationFactory类中找到),该配置项将指定log4j2的配置文件所在位置。注意这个配置项是可以指定多个配置文件的,你需要做的只是使用逗号将它们分开(注意这个逗号目前是写死在代码里的,具体位置是ConfigurationFactory.Factory类的getConfiguration(LoggerContext, String, URI)方法中)。
  2. 第一步提到的配置项,你需要将其放到classpath下新建的log4j2.component.properties文件中(该文件名是在PropertiesUtil类中定义的)。
  3. 第二步有一个替换操作,就是将log4j.configurationFile的配置项注册到系统属性中。
  4. 以上三步的逻辑主要涉及到ConfigurationFactory.Factory.getConfiguration()PropertiesUtil.getProperties().getStringProperty()。读者可自行阅读相应的源码来做到成竹于胸。
  5. 最后给出一个配置示例:
# 定义在classpath下的 log4j2.component.properties 文件
log4j.configurationFile=log4j2-test.xml,log4j2-test2.xml
  1. 关于配置之间的属性覆盖问题以及其他实现细节,可以参见官方文档说明,笔者就不重复了。

注意

  • 这种方式之下,每个配置文件必须满足log4j2.xml的格式,例如XML情况下要以<Configuration>为根节点。
  1. XML Inclusions (XInclude)
  2. StackOverflow - log4j2 - include
  3. log4j2-XInlcude官方文档
  4. 自定义Log4j2配置文件位置

相关文章