博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java_log_02
阅读量:4691 次
发布时间:2019-06-09

本文共 22101 字,大约阅读时间需要 73 分钟。

 

配置

在第一部分,我们将介绍配置 logback 的各种方法,给出了很多配置脚本例子。在第二

部分,我们将介绍 Joran,它是一个通用配置框架,你可以在自己的项目里使用 Joran

一.Logback里的配置

把记录请求插入程序代码需要相当多的计划和努力。 有观察显示大约 4%的代码是记录。

所以即使是一个中等规模的应用程序也会包含数以千计的记录语句。 考虑到数量庞大, 我们
需要使用工具来管理记录语句。

Logback 可以通过编程式配置,或用 XML 格式的配置文件进行配置。

Logback 采取下面的步骤进行自我配置:

1. 尝试在 classpath 下查找文件 logback-test.xml;

2. 如果文件不存在,则查找文件 logback.xml;
3. 如果两个文件都不存在,logback 用 BasicConfigurator 自动对自己进行配置,这会
导致记录输出到控制台。
第三步也是最后一步是为了在缺少配置文件时提供默认(但基本的)记录功能。

 

二,自动配置

最简单的配置方法就是使用默认配置。

BasicConfigurator 用法的简单例子:

package test02;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class Foo {    static final Logger logger=LoggerFactory.getLogger(Foo.class);    public void doIt(){        logger.debug("Did it again!");    }}
package test02;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class MyApp1 {    final static Logger logger=LoggerFactory.getLogger(MyApp1.class);    public static void main(String[] args) {        logger.info("Entering application.");        Foo foo=new Foo();        foo.doIt();        logger.info("Exiting application");    }}

 

假设配置文件 logback-test.xml 和 logback.xml 都不存在,那么 logback 默认地会调用

BasicConfigurator , 创 建一 个 最小 化配 置 。最 小化 配置 由 一个 关联 到 根 logger 的
ConsoleAppender 组成。输出用模式为%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}
- %msg%n 的 PatternLayoutEncoder 进行格式化。还有,根 logger 默认级别是 DEBUG。

运行结果:

MyApp1 程序通过调用 org.slf4j.LoggerFactory 类和 org.slf4j.Logger 类连接到 logback,

取得想 要的 logger, 然后 继续 。注 意 Foo 类 对 logback 唯 一的 依赖 是通 过引入
org.slf4j.LoggerFactory 和 org.slf4j.Logger。

 

三.用用 logback-test.xml 或 或 logback.xml  自动 配置

前面提到过, 如果 classpath 里有 logback-test.xml 或 logback.xml, logback 会试图用它进

行自我配置。下面的配置文件与刚才的 BasicConfigurator 等效

在classpath下创建logback.xml文件内容如下:

 

%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

 

运行结果:

 

四,自动打印警告和错误消息

当解析配置文件有警告或出错时,logback 会在控制台上自动打印状态数据。如果没有

警告或错误, 你还是想检查 logback 的内部状态的话, 可以调用 StatusPrinter 的 print()方法。
MyApp2 程序等价于 MyApp1,只是多了两行打印内部状态数据的代码。
示例:打印 logback 的内部状态信息

package test02;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import ch.qos.logback.classic.LoggerContext;import ch.qos.logback.core.util.StatusPrinter;public class MyApp2 {    final static Logger logger = LoggerFactory.getLogger(MyApp2.class);    public static void main(String[] args) {        // assume SLF4J is bound to logback in the current environment        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();        // print logback's internal status        StatusPrinter.print(lc);                logger.info("Entering application.");        Foo foo = new Foo();        foo.doIt();        logger.info("Exiting application.");    }}

 

运行结果:

 

在输出的最后面,你可以看到上例输出的内容。你也应当注意到 logback 的内部消息,

也就是 Status 对象,它可以方便地访问 logback 的内部状态。

可以不用从代码里调用 StatusPrinter,而是在配置文件里进行相关配置,即使没有出现
错误。方法是,设置 configuration 元素的 debug 属性为 true。请注意 debug 属性只与状态数
据有关,它不影响 logback 的配置,更不会影响记录级别。

现在我将MyApp2修改成:

 

package package01;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Created by Administrator on 2016/7/15. */public class MyApp1 {    final static Logger logger= LoggerFactory.getLogger(MyApp1.class);    public static void main(String[] args) {        //LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();        // print logback's internal status        //StatusPrinter.print(lc);        logger.info("Entering application.");        Foo foo = new Foo();        foo.doIt();        logger.info("Exiting application.");    }}

 

 

 

 然后将我的logback.xml中的debug属性打开:

%d{--HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

 

再运行:

发现结果是一样的.

 

把 configuration 元素的 debug 属性设为 true 后,会输出状态信息,但是前提是:

1.  找到了配置文件;
2.  配置文件是格式化良好的 XML。
如果其中任一条件未满足,Joran 就会因为配置文件不可读而无法读取 debug 属性。如
果找到了配置文件,但却不是格式化良好的,那么 logback 会检测出错误并把内部状态打印
到控制台。然而,如果找不到配置文件,由于这不是个严重的错误,logback 不会自动打印
状态数据。使用编程式的主动调用 StatusPrinter.print()可以确保始终打印状态信息,如
MyApp2。

 

随便说一下:debug属性设为true等效于加了一个OnConsoleStatusListener的Listener

%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

 

 

五.把默认配置文件的位置作为系统属性进行指定

设置名为 logback.configurationFile 的系统属性,把默认配置文件的位置作为属性值,这

种方法也可以。属性值即配置文件位置可以是个 URL、classpath 里的一个资源,或者是程
序外部的文件路径。

java -Dlogback.configurationFile=/path/to/config.xml package01.MyApp1

 

 

六.配置文件修改后自动重新加载

如果设置成自动重新加载,logback-classic 会扫描配置文件里的变化,并且当发生变化

后进行重新配置。设置访方法是设 configuration 元素的 scan 属性为 true。
示例:扫描配置文件的变化并自动重新配置

...

 

 

默认情况下, 每隔一分钟扫描一次。 configuration 元素的 scanPeriod 属性控制扫描周期,

其值可以带时间单位,包括:milliseconds、seconds、minutes 和 hours。
示例:指定不同的扫描周期

...

 

如果没写明时间单位,则默认为毫秒。

内部实现是这样的, 当设置扫描属性为 true 时, 会安装一个叫 ReconfigureOnChangeFilter
的 TurboFilter。每次调用 logger 的打印方法时,都会进行扫描。比如,当名为 myLogger 的
logger执行 “myLogger.debug("hello");” 时, 如果scan属性为true, 则ReconfigureOnChangeFilter
会被调用。而且,即使 myLogger 的 debug 级别被禁用了,仍然会调用上述过滤器。

考虑到在任何 logger 在每次被调用时都要调用 ReconfigureOnChangeFilter,这个过滤器
的性能就变得十分关键了。 为提高性能, 不会在每个 logger 被调用时去检查是否需要扫描,
而是每隔 16 次记录操作进行一次检查。 简言之, 当配置文件改变后, 它会被延时重新加载,
延时时间由扫描间隔时间和一些 logger 调用所决定。

 

七.直接调用 JoranConfigurator

Logback 依赖 Joran,Joran 是 logback-core 的一部分,是个配置类库。Logback 的默认配

置机制是调用JoranConfigurator对classpath上的默认配置文件进行处理。 不管出于什么理由,
如果你想重新实现 logback 的默认配置机制的话,你可以直接调用 JoranConfigurator。下面
没的程序 MyApp3 就调用了 JoranConfigurator 对作为参数传入的配置文件进行处理。
示例:直接调用 JoranConfigurator

package package01;import ch.qos.logback.classic.LoggerContext;import ch.qos.logback.classic.joran.JoranConfigurator;import ch.qos.logback.core.joran.spi.JoranException;import ch.qos.logback.core.util.StatusPrinter;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Created by Administrator on 2016/7/15. */public class MyApp3 {    final static Logger logger= LoggerFactory.getLogger(MyApp3.class);    public static void main(String[] args) {        LoggerContext context= (LoggerContext) LoggerFactory.getILoggerFactory();        JoranConfigurator configurator=new JoranConfigurator();        configurator.setContext(context);        context.reset();        try {            configurator.doConfigure(args[0]);        } catch (JoranException e) {            e.printStackTrace();        }        StatusPrinter.printInCaseOfErrorsOrWarnings(context);        logger.info("Entering application.");        Foo foo = new Foo();        foo.doIt();        logger.info("Exiting application.");    }}

 

运行结果:

本程序直接取得 LoggerContext,创建新 JoranConfigurator 并设置它要操作的上下文,

重置 logger 上下文,最后要求配置器用参数中的配置文件对上下文进行配置。同时打印了
内部状态数据。

八.让包数据生效

在1.1.4的版本去,默认情况下将数据给禁止了.

如果需要,logback可以将有关包数据的堆栈跟踪行信息给输出来.包数据包含了Jar文件的名称,版本,堆栈跟踪行的来源.当我们包数据标识软件版本问题的时候,包数据信息就很有用了.然而却要付出很大的性能代价,特别是对一些异常发生频率较高的应用程序.下面是一段相关的包数据信息:

启用包数据显示的方式,一个是通过配置文件,二个是通过API分别如下:

配置文件:

...

 

LoggerContext中的setPackagingDataEnabled(true)方法:

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();  lc.setPackagingDataEnabled(true);

 

 

九:查看状态消息

Logback 把内部数据放在一个 StatusManager 对象里,并通过 LoggerContext 访问。

StatusManager 通过 logback 上下文来访问所有数据对象。 为把内存占用保持在合理的范
围内,默认的 StatusManager 实现将状态消息按头和尾两部分存储。头部存储开始的 H 条状
态消息,尾部存储后面的 T 条消息。现在的 H=T=150,将来或许会改变。

Logback-classic 带了一个叫 ViewStatusMessagesServlet 的 Servlet, 它以 HTML 表格的格
式打印与当前 LoggerContext 关联的 StatusManager 的内容。示例如下。

click to enlarge

 

要加到自己的 web 应用程序里,可以在 WEB-INF/web.xml 里添加如下内容

ViewStatusMessages
ch.qos.logback.classic.ViewStatusMessagesServlet
ViewStatusMessages
/lbClassicStatus

 

访问地址是 http://host/yourWebapp/lbClassicStatus

 

十:监听状态消息

你也可以为 StatusManager 附加一个 StatusListener, 这样就能立即对状态消息作出响应,

尤其对那些 logback 配置完成之后的消息。注册一个状态监听器可以方便地实现对 logback
内部状态的无人监管。

Logback 带了一个叫 OnConsoleStatusListener 的 StatusListener 实现,可以把状态消息打
印到控制台。

下例演示了如何为 StautsManager 注册一个 OnConsoleStatusListener 实例。

package package01;import ch.qos.logback.classic.LoggerContext;import ch.qos.logback.core.status.OnConsoleStatusListener;import ch.qos.logback.core.status.StatusManager;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Created by Administrator on 2016/7/15. */public class MyApp1 {    final static Logger logger= LoggerFactory.getLogger(MyApp1.class);    public static void main(String[] args) {        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();        StatusManager manager=lc.getStatusManager();        OnConsoleStatusListener listener=new OnConsoleStatusListener();        manager.add(listener);        // print logback's internal status        //StatusPrinter.print(lc);        logger.info("Entering application.");        Foo foo = new Foo();        foo.doIt();        logger.info("Exiting application.");    }}

 

 

还可以通过设置 Java 系统属性“logback.statusListenerClass”注册状态监听器,例如,

java -Dlogback.statusListenerClass=ch.qos.logback.core.status.OnConsoleStatusListener ..

 

 

十一.终止logback-classic

为了释放logback-classic所用的资源,终止logback context是一个很好我办法.终止context会将所有context定义的依赖于loggers的appenders给关闭掉,而且还停止所有的活动的线程

import org.sflf4j.LoggerFactory;import ch.qos.logback.classic.LoggerContext;...// assume SLF4J is bound to logback-classic in the current environmentLoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();loggerContext.stop();

 

如果是在web应用中,上面的代码可以用ServletContextListener中的contextDestroyed的方法的执行.

也可以通过Shutdown hook来终止

使用一个JVM的shutdown hook是一个便捷的方法来关掉logback

....

 

提示:查看API文档可以发现.通过public void setDelay( delay)--------> public Duration(long millis)来设置关闭的延迟时间

 

十二.配置文件语法

到目前为止,正如你已经在这份手册里看到的不少例子,logback 允许你重新定义记录

行为而不必重新编译你的代码。实际上,你可以轻易地配置 logback,比如禁用程序里某些
地方的记录功能,或者直接输出到一个 UNIX 系统守护进程、数据库、日志查看器,或把记
录事件发送到远程 logback 服务器,远程 logback 服务器按照其本地策略进行记录,比如把
记录时间发送到第二个 logback 服务器。

本节剩余部分介绍配置文件的语法。

Logback 配置文件的语法非常灵活。正因为灵活,所以无法用 DTD 或 XML schema 进
行定义。尽管如此,可以这样描述配置文件的基本结构:以<configuration>开头,后面有零
个或多个<appender>元素,有零个或多个<logger>元素,有最多一个<root>元素。如下图所
示:

 

标记名大小写敏感性

从 logback 0.9.17 版起, 标记名不区分大小些。 比如, <logger>、 <Logger>和<LOGGER>

都是合法元素且表示同一个意思。 按照隐式规则, 标记名除了首字母外要区分大小写。 因此,
<xyz>与<Xyz>等价,但不等价于<xYz>。隐式规则一般遵循 Java 世界里常用的驼峰命名规
则。因为很难确定一个标记什么时候与显式动作相关,什么时候又与隐式动作相关,所以很
难说 XML 标记是否是大小写敏感。如果你不确定标记名的大小写,就用驼峰命名法,基本
不会错。

 

配置 logger ,或<logger>

Logger 是用<logger>元素配置的。<logger>元素有且仅有一个 name 属性、一个可选的

level 属性和一个可选的 additivity 属性。

Level 属性的值大小写无关,其值为下面其中一个字符串:TRACE、DEBUG、INFO、
WARN、ERROR、ALL 和 OFF。还可以是一个特殊的字符串“INHERITED”或其同义词
“NULL” ,表示强制继承上级的级别。

<logger>元素可以包含零个或多个<appender-ref>元素,表示这个 appender 会被添加到
该 logger。强调一下,每个用<logger>元素声明的 logger,首先会移除所有 appender,然后
才添加引用了的 appender, 所以如果 logger 没有引用任何 appender, 就会失去所有 appender。

 

  配置根 logger ,或<root> 元素

<root>元素配置根 logger。该元素有一个 level 属性。没有 name 属性,因为已经被命名

为“ROOT” 。

Level 属性的值大小写无关,其值为下面其中一个字符串:TRACE、DEBUG、INFO、
WARN、ERROR、ALL 和 OFF。注意不能设置为“INHERITED” 或“NULL” 。

<logger>元素可以包含零个或多个<appender-ref>元素。 与<logger>元素类似, 声明<root>
元素后,会先关闭然后移除全部当前 appender,只引用声明了的 appender。如果 root 元素没
有引用任何 appender,就会失去所有 appender。

 

示例一:

假设我们不想看到“package01”包里的任何组件的任何 DEBUG 信息,可以

设置如下:
示例:设置 logger 级别

%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

 

package package01;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Created by Administrator on 2016/7/15. */public class MyApp1 {    final static Logger logger= LoggerFactory.getLogger(MyApp1.class);    public static void main(String[] args) { logger.info("Entering application.");        Foo foo = new Foo();        foo.doIt();        logger.info("Exiting application.");    }}

 

运行结果:

 

你 可 以为 任意 数 量的 logger 设 置级 别。 下面 的 配置 文件 里, 我 们为 logger

“package01”设置级别为 INFO,同时设置 logger“package01.Foo”
级别为 DEBUG。

示例二:

%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

 

package package01;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Created by Administrator on 2016/7/15. */public class MyApp1 {    final static Logger logger= LoggerFactory.getLogger(MyApp1.class);    public static void main(String[] args) { logger.info("Entering application.");        Foo foo = new Foo();        foo.doIt();        logger.info("Exiting application.");    }}
View Code

 

 

运行结果:

注意, 基本选择规则依赖于被调用的logger的有效级别, 而不是 appender所关联的 logger

的级别。 Logback 首先判断记录语句是否被启用, 如果启用, 则调用logger 等级里的 appender,
无视 logger 的级别。配置文件 sample4.xml 演示了这一点。

 

示例三:

%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

 

package package01;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Created by Administrator on 2016/7/15. */public class MyApp1 {    final static Logger logger= LoggerFactory.getLogger(MyApp1.class);    public static void main(String[] args) { logger.info("Entering application.");        Foo foo = new Foo();        foo.doIt();        logger.info("Exiting application.");    }}
View Code

 

运行结果:

 

十三.配置 Appender

Appender 用<appender>元素配置,该元素必要属性 name 和 class。

name 属性指定 appender 的名称,class 属性指定 appender 类的全限定名。

<appender>元素可以包含零个或多个<layout>元素、零个或多个<encoder>元素和零个或
多个<filter>元素。 除了这三个常用元素之外, 还可以包含 appender 类的任意数量的 javabean
属性。下图演示了常用结构,注意对 javabean 属性的支持在图中不可见。

<layout>元素的 class 属性是必要的,表示将被实例化的 layout 类的全限定名。和

<appender>元素一样, <layout>元素可以包含 layout 的的 javabean 属性。因为太常用了,所
以当当 layout 是 PatternLayout 时,可以省略 class 属性。

<encoder>元素 class 属性是必要的,表示将被实例化的 encoder 类的全限定名。因为太
常用了,所以当当 encoder 是 PatternLayoutEncoder 时,可以省略 class 属性。

记录输出到多个 appender 很简单,先定义各种 appender,然后在 logger 里进行引用,
就行了。如下面的配置文件所示:

myApp.log
%date %level [%thread] %logger{10} [%file:%line] %msg%n
%msg%n

 

该配置文件定义了两个 appender,分别是“FILE”和“STDOUT” 。

“ FILE” 这 个 appender 把 记 录 输 出 到 文 件 “ myapp.log ” , 它 的 encoder 是
PatternLayoutEncoder,输出了日期、级别、线程名、logger 名、文件名及记录请求的行号、
消息和行分隔符。

“STDOUT”这个 appender 把记录输出到控制台,它的 encoder 只是输出消息和行分隔
符。

注意每个 appender 都有自己的 encoder。Encoder 通常不能被多个 appender 共享,layout
也是。所以,logback 的配置文件里没有共享 encoder 或 layout 的语法。

 

Appender累积

默认情况下,appender 是可累积的:logger 会把记录输出到它自身的 appender 和它所有

祖先的 appender。因此,把同一 appender 关联到多个 logger 会导致重复输出。

示例:重复的 appender

%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

 

执行代码:

package package01;import ch.qos.logback.classic.LoggerContext;import ch.qos.logback.core.util.StatusPrinter;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Created by Administrator on 2016/7/15. */public class MyApp1 {    final static Logger logger= LoggerFactory.getLogger(MyApp1.class);    public static void main(String[] args) {        // assume SLF4J is bound to logback in the current environment        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();        // print logback's internal status        StatusPrinter.print(lc);        logger.info("Entering application.");        Foo foo = new Foo();        foo.doIt();        logger.info("Exiting application.");    }}
View Code

 

运行结果:

看到重复输出了吧?名为 STDOUT 的 appender 被关联给两个 logger,分别是根和

package01。由于根 logger 是所有 logger 的祖先,package01 是
package01.MyApp1 和 package01.Foo 之父,所以这两个 logger 的记录
请求会被输出两次。一次是因为 STDOUT 被关联到 package01,一次是因为被关
联到根 logger。

Appender 的叠加性对新手来说并不是陷阱,反而是非常方便的。举例来说,你可以让
某些系统里所有 logger 的记录信息出现在控制台,却让某些特定 logger 的记录信息发到一
个特定的 appender。

 

示例:重复的 appender

myApp.log
%date %level [%thread] %logger{10} [%file:%line] %msg%n
%msg%n

 

package package01;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Created by Administrator on 2016/7/15. */public class MyApp1 {    final static Logger logger= LoggerFactory.getLogger(MyApp1.class);    public static void main(String[] args) { logger.info("Entering application.");        Foo foo = new Foo();        foo.doIt();        logger.info("Exiting application.");    }}
View Code

本例中,控制台 appender 会输出所有消息(出自系统里的所有 logger) ,但是只有来自

package01 这个 logger 的消息会输出到文件 myApp.log。

 

 覆盖默认的累积行为

如果你觉得默认的累积行为不合适, 可以设置叠加性标识为 false 以关闭它。 这样的话,

logger 树里的某个分支可以输出到与其他 logger 不同的 appender

示例:叠加性标识

foo.log
%date %level [%thread] %logger{10} [%file : %line] %msg%n
%msg%n

 

本例中,logger“package01.Foo”关联 appender“FILE” ,它的叠加性标记为

false,这样它的记录输出仅会被发送到 appender“FILE” ,不会被发送到更高 logger 等级关
联的 appender。其他 logger 不受此影响。

用 additivityFlag.xml 配 置 MyApp1 , 运 行 后 , 控 制 台 上 由 输 出 由

“package01.MyApp1”产生的记录。而 logger“ package01.Foo”将且
仅仅将输出到文件 foo.log。

 

设置上下文名称

每个 logger 都关联到 logger 上下文。默认情况下,logger 上下文名为“default” 。但是

你可以借助配置指令<contextName>设置成其他名字。注意一旦设置 logger 上下文名称后,
不能再改。设置上下文名称后,可以方便地区分来自不同应用程序的记录。

myAppName
%d %contextName [%t] %level %logger{36}- %msg%n

 

本例演示了 logger 上下文的命名方法:在 layout 模式里添加“%contextName”就会输

出上下文的名称。

 

变量替换

原则上,指定变量的地方就能够发生变量替换。变量替换的语法与 Unix shell 中的变量

替换相似。位于“${”与“}”之间的字符串是键(key) ,取代键的值可以在同一配置文件
里指定, 也可以在外部文件或通过系统属性进行指定。 例如, 如果设系统属性 “java.home.dir”
为“/home/xyz” ,那么每次当${java.home.dir}出现时都会被解释为“/home/xyz” 。Logback
自动定义了一个常用变量“${HOSTNAME}” 。

属性被插入 logger 上下文

注意通过<property>元素定义的值实际上会被插入 logger 上下文。换句话说,这些值变

成了 logger 上下文的属性。所以,它们对所有记录事件都可用,包括通过序列化方式被发
送到远程主机的记录事件。

下面的例子在配置文件的开头声明了一个变量又名替换属性,它代表输出文件的位置,
然后在后面的配置文件里使用它。

示例:简单变量替换

${USER_HOME}/myApp.log
%msg%n

 

 

下一个例子用系统属性实现了同样的功能。属性没有在配置文件里声明,因此 logback

会从系统属性里找。Java 系统属性用下面的命令行进行设置:

java -DUSER_HOME="/home/sebastien" MyApp2

 

示例:系统变量替换

${USER_HOME}/myApp.log
%msg%n

 

当需要很多变量时,更方便的做法是在一个单独的文件里声明所有变量,如下例所示。

示例:文件变量替换

${USER_HOME}/myApp.log
%msg%n

这个配置文件包含对文件“variables1.properties”的引用,该文件里的变量会被读入

logback 配置文件的上下文里。
文件“variables1.properties”内容类似于:
示例:变量文件

USER_HOME=/home/sebastien

 

 

还可以不引用文件,而是引用 class path 上的资源

${USER_HOME}/myApp.log
%msg%n

 

 

  嵌套变量替换

Logback 支持嵌套变量替换。这里的嵌套是指变量的值里包含对其他变量的引用。假设

你希望用变量指定目的地目录和文件名,然后用一个变量“destination”组合这两个变量,
如下面所示。
示例:嵌套变量替换variables2.properties

USER_HOME=/home/sebastienfileName=myApp.logdestination=${USER_HOME}/${fileName}

注意在上面的属性文件里, “destination” 由另外两个变量 “USER_HOME” 和 “fileName”

组合而成。

${destination}
%msg%n

 

 

变量的默认替换值

在某些特定情况下,最好给变量一个默认值,以免变量未被声明或值为 null。Bash shell

用“:-”指定默认值。例如,假设“aKey”未被声明,那么“${aKey:-golden}”将被解释为
“golden” 。

 

HOSTNAME

HOSTNNAME 属性因为很常用,所以在配置过程中被自动定义。

 

 设置时间戳

元素 timestamp 可以定义表示一个当前日期和时间的属性。

 

在运行中定义属性

可以配置文件里用<define>元素定义属性。 <define>元素有两个必要属性: name 和 class。

name 属性代表属性的名称, class 属性代表 PropertyDefiner 接口的任意实现。 PropertyDefiner
接口的 getPropertyV alue()方法返回的值就是属性值。
如下例。

of a.class.implementing.PropertyDefiner

Logback 目前还没有提供 PropertyDefiner 接口的具体实现, 只是为动态定义属性提供了

一种方法。

 

  配置文件里的条件 化处理

开发者经常需要针对不同的环境在不同的配置文件里换来换去, 比如开发、 测试和生产

环境。这些配置文件大同小异。为避免重复劳动,logback 支持在配置文件里进行条件化处
理,用<if>、<then>和<else>这些元素可以让一个配置文件适用于多个环境。

条件语句一般格式如下。

...
...
...

 

其中“condition”是 java 表达式,只允许访问上下文属性和系统属性。对于作为参数传

入的键,property()方法或其等价的 p()方法将返回属性的字符串值。例如,想访问属性键为
“k” 的值, 你可以用 property("k")或等价的 p("k")。 如果键为 “k” 的属性未被定义, property
方法将返回空字符串而不是 null,这样避免了检查 null 值。

 

下一个例子里,ConsoleAppender 被关联到根 logger,但是前提条件是 HOSTNAME 属

性的值是“torino” 。注意名为“FILE”的 FileAppender 在任何情况下都被关联到根 logger。

%d %-5level %logger{35} - %msg %n
${randomOutputDir}/conditional.log
%d %-5level %logger{35} - %msg %n

 

<configuration>元素之内的任何地方都支持条件化处理。 也支持嵌套的 if-then-else 语句。

然而,加入过多的条件语句会导致 XML 文件非常难读。

 

从JNDI获取变量

在某些特定情况下, 你也许利用 JNDI 里存储的 env 项, <insertFromJNDI>指令会从JNDI

里取得 env 项,然后用 as 属性把它们作为变量。
示例:通过 JNDI 取得 env 项并作为属性插入

${appName}
%d %contextName %level %msg %logger{50}%n

 

本例中,env 项“java:comp/env/appName”被作为“appName”属性插入到配置文件。

注意先是<insertFromJNDI>指令插入的“appName”属性,然后<contextName>指令把
“appName”的值设成“contextName” 。

 

  文件包含

Joran 支持在配置文件里包含其他文件。方法是声明<include>元素,如下所示:

示例:文件包含

 

被包含的文件必须把它的元素嵌套在<included>元素里。例如,可以这样声明

ConsoleAppender:
示例:文件包含includedConfig.xml

"%d - %m%n"

 

请再次注意<included>元素是必需的

 

被包含的内容可以是文件、资源或 URL。

1. 作为文件
用“file”属性包含一个文件。可以用相对路径,但是需要注意,当前目录是由应
用程序决定的,与配置文件的路径必要的联系。
2. 作为资源
用“resource”属性包含一个资源,也就是在 class path 上的文件。
<include resource="includedConfig.xml" />
3. 作为 URL
用“url”属性包括一个 URL。
<include url="http://some.host.com/includedConfig.xml" />

转载于:https://www.cnblogs.com/wangyang108/p/5674461.html

你可能感兴趣的文章
PHP echo 和 print 语句
查看>>
第一讲 一个简单的Qt程序分析
查看>>
Centos 6.5下的OPENJDK卸载和SUN的JDK安装、环境变量配置
查看>>
poj 1979 Red and Black(dfs)
查看>>
【.Net基础03】HttpWebRequest模拟浏览器登陆
查看>>
zTree async 动态参数处理
查看>>
Oracle学习之常见错误整理
查看>>
lock_sga引起的ksvcreate :process(m000) creation failed
查看>>
数据库插入数据乱码问题
查看>>
OVER(PARTITION BY)函数用法
查看>>
altium annotate 选项设置 complete existing packages
查看>>
【模式识别与机器学习】——SVM举例
查看>>
【转】IT名企面试:微软笔试题(1)
查看>>
IO流入门-第十章-DataInputStream_DataOutputStream
查看>>
DRF的分页
查看>>
Mysql 模糊匹配(字符串str中是否包含子字符串substr)
查看>>
python:open/文件操作
查看>>
流程控制 Day06
查看>>
Linux下安装Tomcat
查看>>
windows live writer 2012 0x80070643
查看>>