理论知识
关于两版的区别
两版的不同,直接的表现是在Maven仓库中log4j 表示第一版,org.apache.logging.log4j 表示第二版。另外应当注意:
- Log4J2.4及更高版本需要Java 7,版本2.0-alpha1至2.3需要Java 6
- XML配置已被简化,与Log4j 1.x不兼容
- 版本2.4开始支持通过属性文件进行配置,但与Log4j 1.x不兼容
- 支持通过JSON或YAML进行配置,但这些格式需要额外的运行时依赖关系
- 虽然Log4j 2与Log4j不直接兼容1.x,但提供了桥接依赖可以减少代码的修改
寻找配置文件的原理
log4j2允许使用log4jConfiguration 上下文参数在web.xml中指定配置文件。Log4j2将通过以下方式搜索配置文件
- 如果提供了一个位置,它将搜索servlet上下文资源,即配置log4jConfiguration
如果没有定义位置,则按照如下所有定位显式配置:
- 检测 log4j.configurationFile 系统属性,如果属性存在,就从它指定的文件中加载配置
- 在类路径上寻找名为 log4j2-test.json 或者 log4j2-test.jsn 的文件,如果文件存在,就从该文件加载配置
- 在类路径上寻找名为 log4j2-test.xml 的文件,如果文件存在,就从该文件加载配置
- 在类路径上寻找名为 log4j2.json 或者 log4j2.jsn 的文件,如果文件存在,就从该文件加载配置
- 在类路径上寻找名为 log4j2.xml 的文件,如果文件存在,就从该文件加载配置
使用类路径和文件URL的正常搜索序列用于定位配置文件
Tomcat版本的差异
出于性能原因,容器经常忽略已知不包含TLD或ServletContainerInitializer的某些JAR,并且不扫描它们的Web片段和初始化器。重要的是,Tomcat 7 <7.0.43将忽略名为log4j * .jar的所有JAR文件,从而阻止此功能的工作。这在Tomcat 7.0.43,Tomcat 8和更高版本中已经修复。在Tomcat 7 <7.0.43中,您将需要更改catalina.properties,并从jarsToSkip 属性中删除”log4j * .jar”。如果他们跳过扫描Log4j JAR文件,您可能需要在其他容器上执行类似的操作。
关于log4j-web的重要性
Log4j2-web.jar文件是配置为在应用程序中的任何其他Web片段之前的Web片段。它包含容器自动发现和初始化的ServletContainerInitializer(Log4jServletContainerInitializer)。这将Log4jServletContextListener和 Log4jServletFilter添加到ServletContext中。这些类正确初始化并初始化Log4j配置。
对于某些用户,自动启动Log4j是有问题的或不合需要的。您可以使用isLog4jAutoInitializationDisabled上下文参数轻松禁用此功能。只需将其添加到您的部署描述符,值为“true”即可禁用自动初始化。您必须在web.xml中定义context参数。如果以编程方式设置,Log4j将检测到设置为时已晚。
<context-param> <param-name> isLog4jAutoInitializationDisabled </ param-name> <param-value> true </ param-value> </context-param>
禁用自动初始化后,您必须像Servlet 2.5 Web应用程序一样初始化Log4j 。您必须这样做,以便在执行任何其他应用程序代码(如Spring Framework启动代码)之前进行此初始化。
您可以自定义侦听器的行为并使用log4jContextName, log4jConfiguration和/或isLog4jContextSelectorNamed上下文参数进行过滤。在下面的“ 上下文参数”部分中阅读更多信息。您不得在部署描述符(web.xml)中或在Servlet 3.0或更高版本应用程序中的其他初始化程序或侦听器中 手动配置Log4jServletContextListener或Log4jServletFilter,除非禁用了使用 isLog4jAutoInitializationDisabled 自动初始化。这样做会导致启动错误和未指定的错误行为。
教程开始
编写pom.xml
<properties> <slf4j.version>1.7.25</slf4j.version> <log4j.version>2.8.2</log4j.version> </properties> <dependencies> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j.version}</version> </dependency> <!--用于与sfl4j保持桥接--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-web</artifactId> <version>${log4j.version}</version> <scope>runtime</scope> </dependency> </dependencies>
注意log4j-web是很重要的,在Java EE Web应用程序中使用Log4j或任何其他日志记录框架时,必须特别小心。由于Web应用程序中的类加载器的性质,Log4j资源无法通过正常方式进行清理。为了避免这些问题,务必包含log4j-web
设置web.xml
Servlet 3.0或更高版本是无需配置web.xml的,它默认指定配置文件应命名为log4j2.xml,并要求放置在classpath中,所以在maven项目里,只要在resources目录下新建log4j2.xml文件即可,否则要设置
<context-param> <param-name>log4jConfiguration</param-name> <param-value>classpath:config/log4j2.xml</param-value> </context-param>
如果项目还是基于Servlet 2.x的,官方声明上Log4j2是不支持Servlet 3.0以下版本的,网上有教程称设置监听器和过滤器,这里给出其参考配置
<listener> <listener-class>org.apache.logging.log4j.web.Log4jServletFilter </listener> <filter> <filter-name>log4jServletFilter</filter-name> <filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class> </filter> <filter-mapping> <filter-name>log4jServletFilter</filter-name> <url-pattern>/*<url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping>
设置配置文件
Log4j2支持properties,xml,json以及yaml。这里给出xml的参考配置
注意命名为log4j2.xml
<?xml version="1.0" encoding="utf-8" ?> <Configuration status="off" monitorInterval="1800"> <properties> <property name="LOG_HOME">F:\logs</property> <property name="ERROR_LOG_FILE_NAME">error</property> </properties> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d %-5p (%F:%L) - %m%n" /> </Console> <RollingRandomAccessFile name="ErrorLog" fileName="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log" filePattern="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log.%d{yyyy-MM-dd}.gz"> <PatternLayout pattern="%d %-5p (%F:%L) - %m%n"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="100MB"/> </Policies> <DefaultRolloverStrategy max="20"/> </RollingRandomAccessFile> </Appenders> <Loggers> <logger name="org.springframework.core" level="info"/> <logger name="org.springframework.beans" level="info"/> <logger name="org.springframework.context" level="info"/> <logger name="org.springframework.web" level="info"/> <logger name="org.newcih" level="error" includeLocation="true" additivity="false"> <appender-ref ref="ErrorLog"/> <appender-ref ref="Console"/> </logger> <root level="info" includeLocation="true"> <appender-ref ref="Console"/> </root> </Loggers> </Configuration>
测试
一般的log4j代码正常使用即可,由于使用到slf4j,这里推荐了lombok,一款简化代码的插件,其实是一个jar包,eclipse和idea有各自的插件可以使用。给出代码如下
import lombok.extern.slf4j.Slf4j; import org.newcih.teacher.service.TeacherService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Slf4j @Controller @RequestMapping("/teacher") public class TeacherManager { @Autowired private TeacherService teacherService; @ResponseBody @RequestMapping(value = "/test") public String test(){ log.info("hello world"); log.error("Hello World"); return "Success"; } }
在上述代码中,控制台和日志文件只会打印Hello World,这里因为在配置文件log4j2.xml中配置到这个包路径下的日志level是error,也就是只记录error级别的日志
教程结束,给出参考的CSDN博客
使用Slf4j集成Log4j2构建项目日志系统的完美解决方案