使用Slf4j集成Log4j2构建项目日志系统的解决方案(不使用Common-logging、Log4j)

1、Log4j、SLF4J、Common-logging的区别

slf4j和commons-logging都是日志框架的规范,本身实现很弱,Log4j主要是针对前两者日志框架的实现。slf4j有取代commons-logging的趋势,common-longing是默认支持log4j的,使用其他日志工具需要做下面的配置:common-logging.properties。

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JCategoryLog

1.1、slf4j

slf4j(全称是Simple Loging Facade For Java)是一个为Java程序提供日志输出的统一接口,并不是一个具体的日志实现方案,就好像我们经常使用的JDBC一样,只是一种规则而已。因此单独的slf4j是不能工作的,它必须搭配其他具体的日志实现方案,比如apache的org.apache.log4j.Logger,jdk自带的java.util.logging.Logger等等。
其中对应的jar包:
    slf4j-log4j12-x.x.x.jar是使用org.apache.log4j.Logger提供的驱动
    slf4j-jdk14-x.x.x.jar是使用java.util.logging提供的驱动
    slf4j-simple-x.x.x.jar直接绑定System.err
    slf4j-jcl-x.x.x.jar是使用commons-logging提供的驱动
    logback-classic-x.x.x.jar是使用logback提供的驱动

1.2、Log4j与Log4j2的区别

log4j是Apache的一个开源项目,log4j2和log4j是一个作者,只不过log4j2是重新架构的一款日志组件,他抛弃了之前log4j的不足,以及吸取了优秀的logback的设计重新推出的一款新组件。log4j2的社区活跃很频繁而且更新的也很快。

1、配置文件类型

log4j是通过一个.properties的文件作为主配置文件的,而现在的log4j 2则已经弃用了这种方式,采用的是.xml,.json或者.jsn这种方式来做。

2、核心JAR包

log4j只需要引入一个jar包即可,

<dependency>
 <groupId>log4j</groupId>
 <artifactId>log4j</artifactId>
 <version>1.2.17</version>
</dependency>

而log4j 2则是需要2个核心

          <!-- slf4j核心包-->  
          <dependency>  
              <groupId>org.slf4j</groupId>  
              <artifactId>slf4j-api</artifactId>  
              <version>1.7.13</version>  
          </dependency>  
          <dependency>  
              <groupId>org.slf4j</groupId>  
              <artifactId>jcl-over-slf4j</artifactId>  
              <version>1.7.13</version>  
              <scope>runtime</scope>  
        </dependency>  

2、使用Slf4j集成Log4j2构建项目日志系统

基于的log4j的日志系统重构成基于Slf4j和log4j2的日志系统,因为,使用slf4j可以很好的保证我们的日志系统具有良好的兼容性,兼容当前常见几种日志系统,而使用log4j2而不是log4j是因为Log4j 1.x 在高并发情况下出现死锁导致cpu使用率异常飙升,而Log4j2.0基于LMAX Disruptor的异步日志在多线程环境下性能会远远优于Log4j 1.x和logback(官方数据是10倍以上)。

2.1搭建步骤

1.依赖管理

1).删除项目中存在的Log4j1.x所必须的log4j和slf4j-log4j12等依赖。
2).添加以下slf4j和log4j2的依赖.

<!--核心log4j2jar包-->
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-api</artifactId>
  <version>2.11.2</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.11.2</version>
</dependency>
<!--用于与slf4j保持桥接-->
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-slf4j-impl</artifactId>
  <version>2.11.2</version>
</dependency>
<!--web工程需要包含log4j-web,非web工程不需要-->
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-web</artifactId>
  <version>2.11.2</version>
</dependency>
<!--下面这个依赖与log4j-slf4j-impl只能二选一,一个是log4j2实现的一个是slf4j实现的-->
<!--
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>1.7.26</version>
</dependency>
-->
<!-- slf4j核心包-->
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.26</version>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>jcl-over-slf4j</artifactId>
  <version>1.7.26</version>
</dependency>

2.web.xml中设置log4j2的监听器和过滤器(servlet3.0及以上版本不需要该步操作)

    <!--对于log4j2,Servlet2.5以前的版本需要-->  
    <listener>  
       <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>  
    </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>  

如何确定自己使用的Servlet版本?

一、确定tomcat的lib文件夹中servlet-api.jar,用记事本打开它的META-INF文件夹中的MANIFEST.MF文件看见下面代码就是版本号

Specification-Version: 3.1

查看jsp版本号也是这样查看,需要打开的是jsp-api.jar文件夹。

二、使用idea的Maven工程时,是需要在pom文件中增加如下依赖的

<dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
</dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/jsp-api -->
<dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
</dependency>

其中scope写的provided意味着打包的时候可以不用包进去,别的设施(Web Container)会提供。事实上该依赖理论上可以参与编译,测试,运行等周期。相当于compile,但是在打包阶段做了exclude的动作。

3、log4j2不再支持properties文件了,只支持xml,json或是yaml,不指定位置的情况下默认在src/main/resources下查找。

如果需要自定义位置,需要在上面的web.xml中添加以下代码

<context-param>  
   <param-name>log4jConfiguration</param-name>  
   <param-value>/WEB-INF/classes/log4j2.xml</param-value>  
</context-param> 

4、log4j2.xml文件详解

<?xml version="1.0" encoding="UTF-8"?>
<!--status日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL-->
<Configuration status="off" monitorInterval="1800">
    <properties>
        <property name="LOG_HOME">/src/logs/</property>
        <property name="ERROR_LOG_FILE_NAME">error</property>
    </properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout  charset="GB18030" pattern="%d %-5p [%t] %C{2} (%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 charset="UTF-8"
                    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="20 MB"/>
            </Policies>
            <DefaultRolloverStrategy max="20"/>
        </RollingRandomAccessFile>
    </Appenders>
    <Loggers>
        <!-- 3rdparty Loggers -->
        <logger name="org.springframework.core" level="error"/>
        <logger name="org.springframework.beans" level="error"/>
        <logger name="org.springframework.context" level="error"/>
        <logger name="org.springframework.web" level="error"/>
        <Logger name="com.opensymphony.xwork2" level="error"/>
        <Logger name="org.apache.struts2" level="error"/>
        <logger name="com.hafiz.www.controller" level="error" includeLocation="true" additivity="false">
            <appender-ref ref="ErrorLog"/>
            <appender-ref ref="Console"/>
        </logger>
        <Root level="warn" includeLocation="true">
            <Appender-ref ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

配置了一个按时间和文件大小滚动的RollingRandomAccessFile的Appender,相比RollingFileAppender有很大的性能提升,官网宣称是20-200%。
Rolling的意思是当满足一定条件后,就重命名原日志文件用于备份,并从新生成一个新的日志文件。例如需求是每天生成一个日志文件,但是如果一天内的日志文件体积已经超过1G,就从新生成,两个条件满足一个即可。这在log4j 1.x原生功能中无法实现,在log4j2中就很简单了。
具体含义
<properties>定义了两个常量方便后面复用

RollingRandomAccessFile的属性:
fileName 指定当前日志文件的位置和文件名称
filePattern 指定当发生Rolling时,文件的转移和重命名规则
SizeBasedTriggeringPolicy 指定当文件体积大于size指定的值时,触发Rolling
DefaultRolloverStrategy 指定最多保存的文件个数
TimeBasedTriggeringPolicy 这个配置需要和filePattern结合使用,注意filePattern中配置的文件重命名规则是${FILE_NAME}-%d{yyyy-MM-dd HH-mm}-%i,最小的时间粒度是mm,即分钟,TimeBasedTriggeringPolicy指定的size是1,结合起来就是每1分钟生成一个新文件。如果改成%d{yyyy-MM-dd HH},最小粒度为小时,则每一个小时生成一个文件。

5、使用很简单
首先引入类

  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;

在类中声明

protected transient Logger logger = LoggerFactory.getLogger(getClass());

**6、**如果控制台中文乱码,改成下边代码试试

<PatternLayout charset="GB18030"  pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />

charset=“GB18030” 把UTF-8改成GB18030。如果控制台乱码则修改控制台的PatternLayout,如果输出文件乱码则修改文件的PatternLayout
问题解决。

可以参考一下
使用Slf4j集成Log4j2构建项目日志系统的完美解决方案

猜你喜欢

转载自blog.csdn.net/u011930054/article/details/88412063