Log4j 2.x XSD的描述不完整

在博客文章JAXB和Log4j XML配置文件中 ,我讨论了“与使用JAXB通过Java类处理[Log4j 1.x和Log4j 2.x] XML配置文件相关的细微差别。” 在本文中,我将探讨另一个与通过Log4j 2.x XML Schema文件Log4j-config.xsd生成的JAXB对象生成Log4j 2.x配置XML相关的挑战:它没有完全指定Log4j 2.x组件的配置特点。

使用Log4j 2.x XML配置时 ,首先要做出的重要区别之一是要使用XML的“ 风味 ”(“简洁”或“严格”)。 简洁的格式可能更容易,因为XML元素的名称对应于它们表示的Log4j 2组件,但是XSD仅支持严格格式。 这意味着从Log4j 2.x XSD生成的JAXB对象中编组的任何XML都必须具有“严格”格式,而不是“简洁”格式。

不幸的是,当前与Log4j 2.x发行版一起提供的XSD( Log4j-config.xsd )不足以生成Log4j 2支持的完整“严格” XML配置。我在这里通过讨论XSD定义的复杂类型来演示这一点。 “ AppenderType ”,因为它是受支持元素在XSD中缺少其潜在属性规范的最极端情况之一。 从Log4j 2.6.2开始,下面的代码清单显示了Log4j-config.xsdAppenderType的定义。

在Log4j 2.6.2的Log4j-config.xsd定义的AppenderType

<xs:complexType name="AppenderType">
   <xs:sequence>
      <xs:element name="Layout" type="LayoutType" minOccurs="0"/>
      <xs:choice minOccurs="0" maxOccurs="1">
         <xs:element name="Filters" type="FiltersType"/>
         <xs:element name="Filter" type="FilterType"/>
      </xs:choice>
   </xs:sequence>
   <xs:attribute name="type" type="xs:string" use="required"/>
   <xs:attribute name="name" type="xs:string" use="required"/>
   <xs:attribute name="fileName" type="xs:string" use="optional"/>
</xs:complexType>

刚刚显示的XSD的摘录告诉我们,以XSD兼容的XML描述的附加器将只能具有三个属性( typenamefileName )中的一个或多个。 “ type ”属性用于标识其附加器的类型(例如“ File ”,“ RollingFile ”,“ Console ”,“ Socket ”和“ Syslog ”)。 问题在于,每个追加程序的“类型”都有不同的属性和特性,理想情况下,可以通过此AppenderType上的属性来描述。

有关AppenderLog4j 2.x文档列出了不同类型的附加程序的特征。 例如,此页面指示ConsoleAppender具有七个参数: filterlayoutfollowdirectnameignoreExceptionstarget 。 该name是由一般所支持的属性之一AppenderType复杂类型和filterlayout通过在嵌套的元件支撑AppenderType 。 但是,可用于ConsoleAppender的其他四个参数在XSD中没有规定定义它们的机制。

甚至不考虑自定义Log4j 2.x附加程序内置的Log4j 2.x附加程序不会共享相同的属性和特征,并且大多数属性具有比AppenderType指定的三个属性和两个嵌套元素更多的特征。 我讨论的七个参数的控制台追加程序以前和其他例子包括RollingFileAppender进行其12个参数( appendbufferedIObufferSizefilterfileNamefilePatternimmediateFlushlayoutnamepolicystrategyignoreExceptions )的JDBCAppender与七个参数( nameignoreExceptionsfilterbufferSizeconnectionSourcetableNamecolumnConfigs )和JMSAppender及其十三个参数( factoryBindingNamefactoryNamefilterlayoutnamepasswordproviderURLdestinationBindingNamesecurityPrincipalNamesecurityCredentialsignoreExceptionsurlPkgPrefixesuserName )。

为了描述XSD中给定的附加器类型可用的每个参数,将需要XML Schema具备以下能力:特定的一组可用属性取决于AppenderTypetype属性的设置。 不幸的是,XML Schema不容易支持这种条件规范,在该条件规范中,给定复杂类型的可用属性基于复杂类型的其他属性之一而不同。

由于模式语言的局限性,想要使用JAXB生成对所有提供的附加程序均具有完全支持的对象的人将需要更改XSD。 一种方法是更改​​XSD,以使AppenderType具有任何内置附加程序的所有可能属性,这些附加属性可用作元素的可选属性。 最明显的缺点是,即使该属性不适用于特定的附加程序类型,XSD也会允许任何附加程序类型具有任何属性。 但是,这种方法将允许JAXB生成的对象将给定附加类型的所有XML属性编组起来。 下一个代码段说明了如何开始。 此处指定了一些不同的追加器所需的其他属性,但是即使更长的列表也不包含支持所有可能的内置追加器类型的属性所需的所有可能的追加器属性。

一些添加到AppenderType Appender属性

<xs:complexType name="AppenderType">
   <xs:sequence>
      <xs:element name="Layout" type="LayoutType" minOccurs="0"/>
      <xs:choice minOccurs="0" maxOccurs="1">
         <xs:element name="Filters" type="FiltersType"/>
         <xs:element name="Filter" type="FilterType"/>
      </xs:choice>
   </xs:sequence>
   <xs:attribute name="type" type="xs:string" use="required"/>
   <xs:attribute name="name" type="xs:string" use="required"/>
   <xs:attribute name="fileName" type="xs:string" use="optional"/>
   <!-- Attributes specified below here are not in Log4j 2.x Log4j-config.xsd -->
   <xs:attribute name="target" type="xs:string" use="optional"/>
   <xs:attribute name="follow" type="xs:string" use="optional"/>
   <xs:attribute name="append" type="xs:string" use="optional"/>
   <xs:attribute name="filePattern" type="xs:string" use="optional"/>
   <xs:attribute name="host" type="xs:string" use="optional"/>
   <xs:attribute name="port" type="xs:string" use="optional"/>
   <xs:attribute name="protocol" type="xs:string" use="optional"/>
   <xs:attribute name="connectTimeoutMillis" type="xs:integer" use="optional"/>
   <xs:attribute name="reconnectionDelayMillis" type="xs:string" use="optional"/>
   <xs:attribute name="facility" type="xs:string" use="optional"/>
   <xs:attribute name="id" type="xs:string" use="optional"/>
   <xs:attribute name="enterpriseNumber" type="xs:integer" use="optional"/>
   <xs:attribute name="useMdc" type="xs:boolean" use="optional"/>
   <xs:attribute name="mdcId" type="xs:string" use="optional"/>
   <xs:attribute name="mdcPrefix" type="xs:string" use="optional"/>
   <xs:attribute name="eventPrefix" type="xs:string" use="optional"/>
   <xs:attribute name="newLine" type="xs:boolean" use="optional"/>
   <xs:attribute name="newLineEscape" type="xs:string" use="optional"/>
</xs:complexType>

更改Log4j 2.x XSD以完全支持所有内置附加程序的第二种方法是将XSD设计从具有由type属性指定的特定类型的单个AppenderType更改为具有许多不同的复杂类型,每个复杂类型分别表示不同的XSD设计。内置的附加器类型。 使用这种方法,XSD可以强制执行任何给定附加程序的所有属性,并且仅与该给定附加程序相关联的属性。 每个追加程序都具有元素类型的这种方法类似于“简洁” XML格式的工作方式,但是当前没有XSD支持。

请注意,我在这里有意专注于内置的附加器类型,因为可以期望静态XSD能够合理,充分且完全地支持它。 此外:可以通过为属性指定任意名称/值对来支持此操作,就像对过滤器或参数进行操作一样 ,但是这还导致能够指定多余的甚至是无用的属性,而架构没有任何能力来捕获这些属性。 支持自定义类型的第三种方法是不使用静态XSD描述语法,而是使用生成的XSD。 可以根据文档中Log4j 2.x组件的描述来手写这样的XSD,但是更好的方法可能是利用Log4j 2.x中使用的@PluginFactory@PluginElement@PluginAttribute注释。源代码。 接下来的两个代码清单来自Apache Log4j 2.6.2代码库,并演示了这些注释如何描述给定类型的元素和属性。

ConsoleAppender.createAppender()签名

@PluginFactory
public static ConsoleAppender createAppender(
   @PluginElement("Layout") Layout layout,
   @PluginElement("Filter") final Filter filter,
   @PluginAttribute(value = "target", defaultString = "SYSTEM_OUT") final String targetStr,
   @PluginAttribute("name") final String name,
   @PluginAttribute(value = "follow", defaultBoolean = false) final String follow,
   @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final String ignore)

SysLogAppender.createAppender()签名

@PluginFactory
public static SyslogAppender createAppender(
   // @formatter:off
   @PluginAttribute("host") final String host,
   @PluginAttribute(value = "port", defaultInt = 0) final int port,
   @PluginAttribute("protocol") final String protocolStr,
   @PluginElement("SSL") final SslConfiguration sslConfig,
   @PluginAttribute(value = "connectTimeoutMillis", defaultInt = 0) final int connectTimeoutMillis,
   @PluginAliases("reconnectionDelay") // deprecated
   @PluginAttribute(value = "reconnectionDelayMillis", defaultInt = 0) final int reconnectionDelayMillis,
   @PluginAttribute(value = "immediateFail", defaultBoolean = true) final boolean immediateFail,
   @PluginAttribute("name") final String name,
   @PluginAttribute(value = "immediateFlush", defaultBoolean = true) final boolean immediateFlush,
   @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions,
   @PluginAttribute(value = "facility", defaultString = "LOCAL0") final Facility facility,
   @PluginAttribute("id") final String id,
   @PluginAttribute(value = "enterpriseNumber", defaultInt = Rfc5424Layout.DEFAULT_ENTERPRISE_NUMBER) final int enterpriseNumber,
   @PluginAttribute(value = "includeMdc", defaultBoolean = true) final boolean includeMdc,
   @PluginAttribute("mdcId") final String mdcId,
   @PluginAttribute("mdcPrefix") final String mdcPrefix,
   @PluginAttribute("eventPrefix") final String eventPrefix,
   @PluginAttribute(value = "newLine", defaultBoolean = false) final boolean newLine,
   @PluginAttribute("newLineEscape") final String escapeNL,
   @PluginAttribute("appName") final String appName,
   @PluginAttribute("messageId") final String msgId,
   @PluginAttribute("mdcExcludes") final String excludes,
   @PluginAttribute("mdcIncludes") final String includes,
   @PluginAttribute("mdcRequired") final String required,
   @PluginAttribute("format") final String format,
   @PluginElement("Filter") final Filter filter,
   @PluginConfiguration final Configuration config,
   @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charsetName,
   @PluginAttribute("exceptionPattern") final String exceptionPattern,
   @PluginElement("LoggerFields") final LoggerFields[] loggerFields, @PluginAttribute(value = "advertise", defaultBoolean = false) final boolean advertise)

这种方法需要几个步骤,因为一个人需要使用Log4j 2.x体系结构主要组成部分的知识以及注释处理来动态生成XSD,然后使用JAXB生成能够封送综合Log4j 2.x的Java类。 XML。

要考虑的另一种选择是使用“简洁的” XML或另一种形式的Log4j 2.x配置 (例如JSON属性文件 ),而不使用XSD生成用于编组Log4j 2.x配置的JAXB对象。 值得注意的是,用于Log4j 2.x且具有“ strict”格式的XML配置文件显然不需要针对Log4j-config.xsd进行验证,否则XML的“ strict”形式将无法完全指定Log4j2组态。 这意味着即使拥有XSD,剩下的价值还是供我们自己的工具或脚本使用,以便在与Log4j 2.x结合使用之前先使用它来验证我们的XML配置,或者用于编组/解编Log4j2.x。带有JAXB的XML。

结论

Log4j2发行版随附的Log4j-config.xsd不足以验证“严格” XML配置中的所有Log4j 2.x构造,同样不足以生成用于封送Log4j2严格XML的JAXB对象。 希望使用XSD进行验证或JAXB类生成的开发人员将需要手动更改XSD或从Log4j2源代码生成XSD。

这些参考文献已在上面的文章中链接到内联,但此处出于强调目的而列出。

翻译自: https://www.javacodegeeks.com/2016/08/log4j-2-x-xsd-not-fully-descriptive.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值