log4j自定义配置文件路径

一 约定优于配置

约定优于配置(convention over configuration),也称作按约定编程,是一种软件设计范式,旨在减少软件开发人员需做决定的数量,获得简单的好处,而又不失灵活性。大量的配置文件,确实可以让程序在一定程度上具有很大的灵活性,但是也要有度的限制,并不是越多越好;约定一些默认的配置,有助于减少配置文件的数量。当然,全部使用约定而不支持配置也是不可取的,必然有失灵活性;因此约定优于配置不代表不是用配置,而是一种要同时提供约定和配置两种方式。

rootAppender约定:
使用log4j打印日志,需要配置日志实例得输出样式以及目的地等等信息,不是必须配置的。
log4j约定了一种无须配置的日志实例的输出方式,提供了一个基本的控制台appender,所有创建的日志实例打印的日志都会按照这个appender输出。
只需要在创建日志实例之前调用默认初始化即可:

static {
    BasicConfigurator.configure();
    logger = LogManager.getLogger(Log4jOneTest.class);
} 

控制台输出格式如下,不输出trace级别日志:

配置文件路径的约定:
log4j约定了配置文件在类路径种的位置,无需在程序中指定配置文件路径,log4j会在其指定的默认类路径下寻找配置,也就是在classpath得根路径:
log4j配置文件路径

二 配置文件如何加载

有时约定在classpaht根路径下的配置文件多了,会导致配置文件没有层次结构,很难发现配置文件的功能;因此此时需要自定义log4j配置文件的路径。
寻找配置文件:
通常,log4j在创建日志实例时都是通过调用LogManager的getLogger(String/Class)方法,分析LogManager的源码,LogManager在初始化时做了以下操作:

static {
        // By default we use a DefaultRepositorySelector which always returns 'h'.
        Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));
        repositorySelector = new DefaultRepositorySelector(h);

        /** Search for the properties file log4j.properties in the CLASSPATH.  */
        // 获取名为log4j.defaultInitOverride的vm变量,该变量决定日志的初始化是否被重载
        String override = OptionConverter.getSystemProperty(DEFAULT_INIT_OVERRIDE_KEY,
                null);

        // if there is no default init override, then get the resource
        // specified by the user or the default config file.
        if (override == null || "false".equalsIgnoreCase(override)) {
            // DEFAULT_CONFIGURATION_KEY的值为log4j.configuration,获取名为log4j.configuration的vm变量
            String configurationOptionStr = OptionConverter.getSystemProperty(
                    DEFAULT_CONFIGURATION_KEY,
                    null);

            String configuratorClassName = OptionConverter.getSystemProperty(
                    CONFIGURATOR_CLASS_KEY,
                    null);

            URL url = null;

            // if the user has not specified the log4j.configuration
            // property, we search first for the file "log4j.xml" and then
            // "log4j.properties"
            // 如果在vm系统变量中没有找到log4j.configuration,则先在classpath根目录找log4j.xml,
            // 再寻找log4j.properties文件
            if (configurationOptionStr == null) {
                url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE);
                if (url == null) {
                    url = Loader.getResource(DEFAULT_CONFIGURATION_FILE);
                }
            } else {
                // 若配置了vm系统变量log4j.configuration,则使用该变量的值作为配置文件的类路径
                try {
                    url = new URL(configurationOptionStr);
                } catch (MalformedURLException ex) {
                    // so, resource is not a URL:
                    // attempt to get the resource from the class path
                    url = Loader.getResource(configurationOptionStr);
                }
            }

            // If we have a non-null url, then delegate the rest of the
            // configuration to the OptionConverter.selectAndConfigure
            // method.
            if (url != null) {
                LogLog.debug("Using URL [" + url + "] for automatic log4j configuration.");
                try {
                    OptionConverter.selectAndConfigure(url, configuratorClassName,
                            LogManager.getLoggerRepository());
                } catch (NoClassDefFoundError e) {
                    LogLog.warn("Error during default initialization", e);
                }
            } else { // 没有找到配置文件则报错
                LogLog.debug("Could not find resource: [" + configurationOptionStr + "].");
            }
        } else {
            LogLog.debug("Default initialization of overridden by " +
                    DEFAULT_INIT_OVERRIDE_KEY + "property.");
        }
    }

因此,LogManager在初始化时:

1.查找log4j.defaultInitOverrideVM系统变量,确认初始化是否重载;
2.没要被重载的情况下,查找log4j.configurationVM系统变量,确认是否自定义配置文件路径;
3.没要配置log4j.configurationVM系统变量,顺序查找根类路径下的log4j.xml,log4j.properties

使用配置文件:
分析LogManager,在查找到配置文件后,调用了:

OptionConverter.selectAndConfigure(url, configuratorClassName, LogManager.getLoggerRepository());

来处理配置,其中url就是配置文件。

static
    public void selectAndConfigure(URL url, String clazz, LoggerRepository hierarchy) {
        Configurator configurator = null;
        String filename = url.getFile();
        // 根据配置文件名后缀选择使用DOMConfigurator还是PropertyConfigurator来处理
        if (clazz == null && filename != null && filename.endsWith(".xml")) {
            clazz = "org.apache.log4j.xml.DOMConfigurator";
        }

        if (clazz != null) {
            LogLog.debug("Preferred configurator class: " + clazz);
            configurator = (Configurator) instantiateByClassName(clazz,
                    Configurator.class,
                    null);
            if (configurator == null) {
                LogLog.error("Could not instantiate configurator [" + clazz + "].");
                return;
            }
        } else {
            configurator = new PropertyConfigurator();
        }
        // 处理配置
        configurator.doConfigure(url, hierarchy);
    }

最后看看DOMConfigurator处理配置文件的doConfigure方法:

public
  void doConfigure(final URL url, LoggerRepository repository) {
      ParseAction action = new ParseAction() {
          public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
              URLConnection uConn = url.openConnection();
              uConn.setUseCaches(false);
              InputStream stream = uConn.getInputStream();
              try {
                InputSource src = new InputSource(stream);
                src.setSystemId(url.toString());
                return parser.parse(src);
              } finally {
                stream.close();
              }
          }
          public String toString() {
              return "url [" + url.toString() + "]";
          }
      };
      doConfigure(action, repository);
  }

可以看到读取了配置文件内容。PropertyConfigurator也是一样的

三 自定义配置文件路径

了解了log4j如何加载配置文件之后,就可以自定义配置文件路径了;

设值vm系统变量:
简单的,在获取logManager初始化值前,通过设置vm系统变量log4j.configuration的值为配置文件路径,可以达到目的:

static {
    String customizedPath = "log/log4j.xml";
    System.setProperty("log4j.configuration", customizedPath);
    logger = LogManager.getLogger(Log4jOneTest.class);
}

PropertyConfigurator或DOMConfigurator:
DOMConfigurator中有一个doConfigure()的static版本,对应xml配置方式,PropertyConfigurator也一样,对应properties配置方式,通过调用这个方法也能指定配置文件位置:

static public void configure(URL url) throws FactoryConfigurationError {
        new DOMConfigurator().doConfigure(url, LogManager.getLoggerRepository());
}

具体如下:

static {
    String customizedPath = "log/log4j.xml";
    DOMConfigurator.configure(getResource(customizedPath));
    logger = LogManager.getLogger(Log4jOneTest.class);
}

参考: 《 关于Log4j的初始化》

要在 `log4j.properties` 中配置自定义日志输出路径,可以按照以下步骤进行操作: 1. 在 `log4j.properties` 文件中添加一个新的 appender,指定日志输出路径。例如: ```properties log4j.appender.custom=org.apache.log4j.RollingFileAppender log4j.appender.custom.File=/path/to/custom.log log4j.appender.custom.MaxFileSize=10MB log4j.appender.custom.MaxBackupIndex=10 log4j.appender.custom.layout=org.apache.log4j.PatternLayout log4j.appender.custom.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c %x - %m%n ``` 在上面的配置中,`custom` 是 appender 的名称,`/path/to/custom.log` 是自定义日志输出路径,`MaxFileSize` 和 `MaxBackupIndex` 分别指定文件大小和备份文件数。 2. 在 `log4j.properties` 文件中指定日志输出目的地。例如: ```properties log4j.rootLogger=INFO, custom ``` 在上面的配置中,`custom` 是上一步中定义的 appender 名称。 3. 在代码中获取 Logger 对象并使用。例如: ```java import org.apache.log4j.Logger; public class MyApplication { private static final Logger logger = Logger.getLogger(MyApplication.class); public static void main(String[] args) { logger.info("Hello, world!"); } } ``` 在上面的代码中,使用 `Logger.getLogger(MyApplication.class)` 获取 Logger 对象,并调用 `logger.info("Hello, world!")` 输出日志信息。日志信息将会输出到自定义的日志输出路径 `/path/to/custom.log`。 注意:如果你已经在 `log4j.properties` 文件中定义了其他的 appender 和日志输出目的地,需要将自定义的 appender 和日志输出目的地添加到现有配置中。例如: ```properties log4j.rootLogger=INFO, console, file, custom log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.Target=System.out log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c %x - %m%n log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.File=/path/to/file.log log4j.appender.file.MaxFileSize=10MB log4j.appender.file.MaxBackupIndex=10 log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c %x - %m%n log4j.appender.custom=org.apache.log4j.RollingFileAppender log4j.appender.custom.File=/path/to/custom.log log4j.appender.custom.MaxFileSize=10MB log4j.appender.custom.MaxBackupIndex=10 log4j.appender.custom.layout=org.apache.log4j.PatternLayout log4j.appender.custom.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c %x - %m%n ``` 在上面的配置中,`console` 和 `file` 是已经定义的 appender 和日志输出目的地,`custom` 是自定义的 appender 和日志输出目的地。注意在 `log4j.rootLogger` 中将它们都添加进去。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值