选择日志库时,必须小心谨慎,以确保正确考虑多个不同的日志库。
例如,您依赖的库代码可能使用 slf4j,而其他库可能只使用 java.util.logging。 所有这些都可以路由到 log4j 核心以便记录。
但是,如果您想使用不同的日志记录实现(例如 logback),则可以将消息从 Log4j API 路由到 logback,确保您的应用程序不依赖于特定的日志记录框架。
使用 Log4j2 API 的典型类如下所示:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Log4j2Test {
private static final Logger logger = LogManager.getLogger();
public Log4j2Test(){
logger.info( "Hello World!" );
}
}
Log4j 2 API 提供了应用程序应该编码的接口,并提供了实现者创建日志实现所需的适配器组件。
虽然 Log4j 2 在 API 和实现之间被分解,但这样做的主要目的不是允许多个实现,尽管这当然是可能的,而是明确定义在“正常”应用程序代码中可以安全使用哪些类和方法 .
你好世界!
如果没有惯用的 Hello, World 示例,任何介绍都是不完整的。
这是我们的。
首先,从 LogManager 中获取名为“HelloWorld”的 Logger。
接下来,记录器用于编写“Hello, World!” 消息,但是只有当 Logger 配置为允许信息性消息时才会写入消息
将日志请求插入到应用程序代码中需要进行大量的计划和工作。
观察表明,大约4%的代码专门用于日志记录。因此,即使是中等规模的应用程序也会在其代码中嵌入数千条日志记录语句。
考虑到它们的数量,必须管理这些日志语句,而不需要手动修改它们。
Log4j 2的配置可以通过以下四种方式之一完成:
-
通过用XML、JSON、YAML或属性格式编写的配置文件。
-
通过编程方式,创建一个ConfigurationFactory和Configuration实现。
-
通过编程方式,调用Configuration接口中公开的api,将组件添加到默认配置中。
-
以编程方式,通过调用内部Logger类上的方法。
与Java中的任何变量一样,logger可以声明为静态变量或类成员变量。
然而,在选择将日志记录器声明为静态还是非静态时,需要考虑一些因素。一般来说,最好将logger声明为静态的。
-
当使用默认的ContextSelector ClassLoaderContextSelector时,实例化一个新的Logger是一个相当昂贵的操作。当Logger被创建时,ClassLoaderContextSelector将定位与Logger关联的类的ClassLoader,并将Logger添加到与该ClassLoader关联的LoggerContext中。
-
一旦创建了Logger,它将不会被删除,直到它所关联的LoggerContext被删除。通常,这只会在应用程序关闭或取消部署时发生。每次调用具有相同logger名称的getLogger将返回相同的logger实例。因此,静态或非静态Logger之间的区别非常小。
-
静态和非静态Logger之间没有行为上的区别。两者在创建时都会分配Logger名称,这通常是与它们相关联的类的名称。有关更多信息,请参阅下面关于记录器名称与类名称的讨论和示例。
在Java EE web应用程序中使用Log4j或任何其他日志框架时,必须特别小心。
当容器关闭或web应用程序取消部署时,正确清理日志资源(关闭数据库连接、关闭文件等)是很重要的。由于web应用程序中的类加载器的特性,Log4j资源不能通过正常方式清理。
当web应用程序部署时,Log4j必须“启动”,当web应用程序取消部署时,Log4j必须“关闭”。如何工作取决于您的应用程序是Servlet 3.0或更新版本还是Servlet 2.5 web应用程序。
由于名称空间从javax更改为jakarta,对于Servlet 5.0或更新版本,您需要使用log4j-jakarta-web而不是log4j-web。
查找提供了一种在任意位置向Log4j配置添加值的方法。它们是实现StrLookup接口的一种特殊类型的Plugin。
有关如何在配置文件中使用查找的信息,可在“配置”页的“属性替换”部分找到。
上下文映射查找
contextmapllookup允许应用程序将数据存储在Log4j ThreadContext Map中,然后检索Log4j配置中的值。
在下面的示例中,应用程序将使用键“loginId”将当前用户的登录id存储在ThreadContext Map中。
在初始配置处理过程中,第一个'$'将被删除。PatternLayout通过查找支持插值,然后为每个事件解析变量。注意,模式“%X{loginId}”将获得相同的结果。
appender负责将LogEvents传递到它们的目的地。每个Appender都必须实现Appender接口。
大多数appender都扩展了AbstractAppender,后者增加了生命周期和可过滤的支持。生命周期允许组件在配置完成后完成初始化,并在关闭期间执行清理。
Filterable允许组件附加过滤器,在事件处理期间对其进行评估。
appender通常只负责将事件数据写入目标目的地。在大多数情况下,他们将格式化事件的责任委托给布局。
一些Appender封装了其他Appender,这样它们就可以修改LogEvent,处理Appender中的故障,根据高级过滤器标准将事件路由到下级Appender,或者提供类似的功能,但不直接格式化事件以供查看。