有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java以编程方式创建复合过滤器,以在log4j 2中定义多个过滤器

要为log4j(版本2)中的一个元素定义多个过滤器,需要一个复合过滤器(根据documentation)。 在使用编程配置时,我不知道如何创建/添加这样的过滤器元素:



    import java.io.IOException;
    import java.net.URI;
    import org.apache.logging.log4j.Level;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.apache.logging.log4j.core.Filter;
    import org.apache.logging.log4j.core.LoggerContext;
    import org.apache.logging.log4j.core.appender.ConsoleAppender;
    import org.apache.logging.log4j.core.config.Configuration;
    import org.apache.logging.log4j.core.config.ConfigurationFactory;
    import org.apache.logging.log4j.core.config.ConfigurationSource;
    import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
    import org.apache.logging.log4j.core.config.builder.api.AppenderRefComponentBuilder;
    import org.apache.logging.log4j.core.config.builder.api.CompositeFilterComponentBuilder;
    import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
    import org.apache.logging.log4j.core.config.builder.api.FilterComponentBuilder;
    import org.apache.logging.log4j.core.config.builder.api.KeyValuePairComponentBuilder;
    import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder;
    import org.apache.logging.log4j.core.config.builder.api.LoggerComponentBuilder;
    import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder;
    import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;

    public class ConfigurationFactory_Demo {
        
        public static void main(String[] args) {
            ConfigurationFactory configurationFactory = new ConfigurationFactoryClass();
            ConfigurationFactory.setConfigurationFactory(configurationFactory);
            Logger logger = LogManager.getLogger("com.logger");
            logger.info( String.format("Logging Event"));
        }
        
        public static class ConfigurationFactoryClass extends ConfigurationFactory {
            @Override
            public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
                return getConfiguration(loggerContext, source.toString(), null);
            }
            @Override
            public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
                ConfigurationBuilder builder = newConfigurationBuilder();
                return createConfiguration(name, builder);
            }
            @Override
            protected String[] getSupportedTypes() {
                return new String[] {"*"};
            }
            
            Configuration createConfiguration(final String configurationName, ConfigurationBuilder configuration) {
                configuration.setConfigurationName(configurationName);
                configuration.setStatusLevel(Level.INFO);
                
                // Create appender:
                AppenderComponentBuilder appenderComponent = configuration.newAppender("stdout", "CONSOLE");
                appenderComponent.addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
                LayoutComponentBuilder layoutComponent = configuration.newLayout("PatternLayout");
                layoutComponent.addAttribute("pattern", "%msg%n");
                appenderComponent.add(layoutComponent);                         // adding layout to appender
                configuration.add(appenderComponent);                            // adding appender to configuration 
                
                // Create root logger:
                RootLoggerComponentBuilder rootLoggerComponent = configuration.newRootLogger(Level.ERROR);
                rootLoggerComponent.add(configuration.newAppenderRef("stdout"));
                configuration.add(rootLoggerComponent);                            // adding logger to configuration

                // Create logger:
                LoggerComponentBuilder loggerComponent = configuration.newLogger("com.logger", Level.TRACE); 
                loggerComponent.addAttribute("additivity", false);
                AppenderRefComponentBuilder appenderRefComponent = configuration.newAppenderRef("stdout");
                appenderRefComponent.addAttribute("level", "TRACE");
                
                // Create filter 'Marker':
                FilterComponentBuilder filterComponent_marker = configuration.newFilter("MarkerFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL);
                filterComponent_marker.addAttribute("marker", "MarkerTag"); 
                // Create filter 'Thread Context Map:
                FilterComponentBuilder filterComponent_threadContextMap;
                filterComponent_threadContextMap = configuration.newFilter("ThreadContextMapFilter", Filter.Result.ACCEPT, Filter.Result.DENY);
                KeyValuePairComponentBuilder keyValuePairComponent;
                keyValuePairComponent = configuration.newKeyValuePair("key", "value");
                filterComponent_threadContextMap.addComponent(keyValuePairComponent);

                boolean useCompositeFilter = false;
                if (useCompositeFilter) {
                    CompositeFilterComponentBuilder filterComponent_composite = null;    // HOW TO INITIALIZE 'CompositeFilterComponentBuilder' ? 
                    filterComponent_composite.add(filterComponent_marker);
                    filterComponent_composite.add(filterComponent_threadContextMap);
                    // appenderRefComponent.add(filterComponent_composite);                // HOW TO ADD 'CompositeFilterComponentBuilder' to appender-reference ?
                } else {
                    appenderRefComponent.add(filterComponent_marker);                    // adding filter directly to appender-reference
                    appenderRefComponent.add(filterComponent_threadContextMap);            // adding second filter directly to appender-reference (NOT ALLOWED)
                }
                
                loggerComponent.add(appenderRefComponent);                                // adding appender-reference to logger 
                configuration.add(loggerComponent);                                        // adding logger to configuration
                
                try { configuration.writeXmlConfiguration(System.out); } catch (IOException e) {}
                
                BuiltConfiguration buildConfiguration = configuration.build();
                return buildConfiguration;
            }
        }
    }

这段Java代码的结果如下所示。它生成错误“AppenderRef没有与元素ThreadContextMapFilter匹配的参数”

<?xml version="1.0" ?>
<Configuration name="18b4aac2" status="INFO">
  <Appenders>
    <CONSOLE name="stdout" target="SYSTEM_OUT">
      <PatternLayout pattern="%msg%n"/>
    </CONSOLE>
  </Appenders>
  <Loggers>
    <Root level="ERROR">
      <AppenderRef ref="stdout"/>
    </Root>
    <Logger name="com.logger" level="TRACE" additivity="false">
      <AppenderRef ref="stdout" level="TRACE">
        <MarkerFilter onMatch="ACCEPT" onMismatch="NEUTRAL" marker="MarkerTag"/>
        <ThreadContextMapFilter onMatch="ACCEPT" onMismatch="DENY">
          <KeyValuePair key="key" value="value"/>
        </ThreadContextMapFilter>
      </AppenderRef>
    </Logger>
  </Loggers>
</Configuration>

正确的配置应为:

<?xml version="1.0" ?>
<Configuration name="18b4aac2" status="INFO">
  <Appenders>
    <CONSOLE name="stdout" target="SYSTEM_OUT">
      <PatternLayout pattern="%msg%n"/>
    </CONSOLE>
  </Appenders>
  <Loggers>
    <Root level="ERROR">
      <AppenderRef ref="stdout"/>
    </Root>
    <Logger name="com.logger" level="TRACE" additivity="false">
      <AppenderRef ref="stdout" level="TRACE">
        <Filters>
          <MarkerFilter onMatch="ACCEPT" onMismatch="NEUTRAL" marker="MarkerTag"/>
          <ThreadContextMapFilter onMatch="ACCEPT" onMismatch="DENY">
            <KeyValuePair key="key" value="value"/>
        </Filters>
        </ThreadContextMapFilter>
      </AppenderRef>
    </Logger>
  </Loggers>
</Configuration>

在这种情况下,如何以编程方式定义复合过滤器


共 (1) 个答案

  1. # 1 楼答案

    可以使用ConfigurationBuilder.newComponent()方法实例化CompositeFilter:

    appenderRefComponent.addComponent(
        configuration.newComponent("filters")
            .addComponent(filterComponent_marker)
            .addComponent(filterComponent_threadContextMap)
    );