一、背景

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

  关于slf4j的原理以及优点,请参见我的另一篇博客:slf4j介绍以及实现原理窥探

二、搭建步骤

  1.依赖管理

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

      可以到项目的根目录,执行:mvn dependency:tree > tree.log,之后使用 cat tree.log | grep log4j命令进行查找。

  1. <exclusions>
  2. <exclusion>
  3. <groupId>org.slf4j</groupId>
  4. <artifactId>slf4j-log4j12</artifactId>
  5. </exclusion>
  6. <exclusion>
  7. <groupId>log4j</groupId>
  8. <artifactId>log4j</artifactId>
  9. </exclusion>
  10. </exclusions>

    2).添加以下slf4j和log4j2的依赖.

  1. <!-- slf4j核心包-->
  2. <dependency>
  3. <groupId>org.slf4j</groupId>
  4. <artifactId>slf4j-api</artifactId>
  5. <version>1.7.13</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.slf4j</groupId>
  9. <artifactId>jcl-over-slf4j</artifactId>
  10. <version>1.7.13</version>
  11. <scope>runtime</scope>
  12. </dependency>
  13.  
  14. <!--核心log4j2jar包-->
  15. <dependency>
  16. <groupId>org.apache.logging.log4j</groupId>
  17. <artifactId>log4j-api</artifactId>
  18. <version>2.4.1</version>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.apache.logging.log4j</groupId>
  22. <artifactId>log4j-core</artifactId>
  23. <version>2.4.1</version>
  24. </dependency>
  25. <!--用于与slf4j保持桥接-->
  26. <dependency>
  27. <groupId>org.apache.logging.log4j</groupId>
  28. <artifactId>log4j-slf4j-impl</artifactId>
  29. <version>2.4.1</version>
  30. </dependency>
  31. <!--web工程需要包含log4j-web,非web工程不需要-->
  32. <dependency>
  33. <groupId>org.apache.logging.log4j</groupId>
  34. <artifactId>log4j-web</artifactId>
  35. <version>2.4.1</version>
  36. <scope>runtime</scope>
  37. </dependency>
  38.  
  39. <!--需要使用log4j2的AsyncLogger需要包含disruptor-->
  40. <dependency>
  41. <groupId>com.lmax</groupId>
  42. <artifactId>disruptor</artifactId>
  43. <version>3.2.0</version>
  44. </dependency>

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

  1. <!--对于log4j2,Servlet2.5以前的版本需要-->
  2. <listener>
  3. <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
  4. </listener>
  5. <filter>
  6. <filter-name>log4jServletFilter</filter-name>
  7. <filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
  8. </filter>
  9. <filter-mapping>
  10. <filter-name>log4jServletFilter</filter-name>
  11. <url-pattern>/*</url-pattern>
  12. <dispatcher>REQUEST</dispatcher>
  13. <dispatcher>FORWARD</dispatcher>
  14. <dispatcher>INCLUDE</dispatcher>
  15. <dispatcher>ERROR</dispatcher>
  16. </filter-mapping>

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

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

  1. <context-param>
  2. <param-name>log4jConfiguration</param-name>
  3. <param-value>/WEB-INF/classes/log4j2.xml</param-value>
  4. </context-param>

  3.log4j2.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2.  
  3. <Configuration status="off" monitorInterval="1800">
  4.  
  5. <properties>
  6. <property name="LOG_HOME">/opt/logs/hafiz/log4j2Demo/logs</property>
  7. <property name="ERROR_LOG_FILE_NAME">error</property>
  8. </properties>
  9.  
  10. <Appenders>
  11. <Console name="Console" target="SYSTEM_OUT">
  12. <PatternLayout pattern="%d %-5p (%F:%L) - %m%n" />
  13. </Console>
  14.  
  15. <RollingRandomAccessFile name="ErrorLog"
  16. fileName="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log"
  17. filePattern="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log.%d{yyyy-MM-dd}.gz">
  18. <PatternLayout
  19. pattern="%d %-5p (%F:%L) - %m%n"/>
  20. <Policies>
  21. <TimeBasedTriggeringPolicy/>
  22. <SizeBasedTriggeringPolicy size="100 MB"/>
  23. </Policies>
  24. <DefaultRolloverStrategy max="20"/>
  25. </RollingRandomAccessFile>
  26.  
  27. </Appenders>
  28.  
  29. <Loggers>
  30. <!-- 3rdparty Loggers -->
  31. <logger name="org.springframework.core" level="info">
  32. </logger>
  33. <logger name="org.springframework.beans" level="info">
  34. </logger>
  35. <logger name="org.springframework.context" level="info">
  36. </logger>
  37. <logger name="org.springframework.web" level="info">
  38. </logger>
  39.  
  40. <logger name="com.hafiz.www.controller" level="error" includeLocation="true" additivity="false">
  41. <appender-ref ref="ErrorLog"/>
  42. <appender-ref ref="Console"/>
  43. </logger>
  44.  
  45. <root level="info" includeLocation="true">
  46. <appender-ref ref="Console"/>
  47. </root>
  48. </Loggers>
  49. </Configuration>

  4.测试类UserController.java

  1. package com.hafiz.www.controller;
  2.  
  3. import com.hafiz.www.po.UserEntity;
  4. import com.hafiz.www.service.UserService;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.stereotype.Controller;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestMethod;
  11. import org.springframework.web.bind.annotation.ResponseBody;
  12.  
  13. import java.util.ArrayList;
  14. import java.util.List;
  15.  
  16. /**
  17. * Desc:用户信息控制器
  18. * Created by hafiz.zhang on 2016/8/27.
  19. */
  20. @Controller
  21. @RequestMapping("/user")
  22. public class UserController {
  23.  
  24. private static final Logger logger = LoggerFactory.getLogger(UserController.class);
  25.  
  26. @Autowired
  27. private UserService userService;
  28.  
  29. @RequestMapping(value = "/all", method = RequestMethod.GET)
  30. @ResponseBody
  31. public List<UserEntity> getAllUsers(){
  32. logger.info("[GET] /user/all getAllUsers");
  33. List<UserEntity> list = userService.getAllUsers();
  34. logger.debug("This is log of level of debug");
  35. logger.trace("log4j2 Demo");
  36. logger.error("哎呀,出错啦~");
  37. return list;
  38. }
  39. }

注意:在JVM启动参数中增加 -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector 开启异步日志.

三、小问题:

  项目不打印日志并且报:SLF4J: Class path contains multiple SLF4J bindings.主要问题在于在项目中既存在slf4j-log4j12的jar包又存在log4j-slf4j-impl的jar包,导致出现了两个打印日志实现类,所以slf4j门面不知道具体应该使用哪一个进行输出日志,所以导致不打印日志。

  因为我之前是log4j 1.x,并且我在web.xml里面指定了log4j.properties文件的位置,第一次运行项目,忘了修改其值为log4j2.xml,出现了"Context [] startup failed due to previous errors"的错误,导致项目启动不起来,web.xml中修改为如下方式以后就正常了。

  1. <context-param>
  2. <param-name>log4jConfiguration</param-name>
  3. <param-value>/WEB-INF/classes/log4j2.xml</param-value>
  4. </context-param>

使用Slf4j集成Log4j2构建项目日志系统的完美解决方案的更多相关文章

  1. java项目日志系统的总结

    目录 日志系统归类以及关系 日志的三个组件 slf4j的使用 项目中构建日志系统 使用例子 日志系统归类以及关系 常用的日志框架: slf4j.logback .log4j.log4j2.JUL(ja ...

  2. 【ELK】5.spring boot日志集成ELK,搭建日志系统

    阅读前必看: ELK在docker下搭建步骤 spring boot集成es,CRUD操作完整版 ============================================== 本章集成 ...

  3. springboot2.7.x 集成log4j2配置写入日志到mysql自定义表格

    在阅读之前请先查看[springboot集成log4j2] 本文暂不考虑抽象等实现方式,只限于展示如何自定义配置log4j2并写入mysql数据库(自定义结构) 先看下log4j2的配置 <?x ...

  4. 利用开源架构ELK构建分布式日志系统

    问题导读 1.ELK产生的背景?2.ELK的基本组成模块以及各个模块的作用?3.ELK的使用总计有哪些? 背景 日志,对每个系统来说,都是很重要,又很容易被忽视的部分.日志里记录了程序执行的关键信息, ...

  5. 记一次项目上线后Log4j2不输出日志的坑

        公司项目采用了Log4j2来输出日志,在开发环境和测试环境下均可以输出日志,但在生成环境就没有日志输出.开始毫无头绪,后来通过不断的排查,终于解决了这个问题.在此记录下该问题的解决过程,便于后 ...

  6. 6 个 K8s 日志系统建设中的典型问题,你遇到过几个?

    作者 |  元乙  阿里云日志服务数据采集客户端负责人,目前采集客户端 logtail 在集团百万规模部署,每天采集上万应用数 PB 数据,经历多次双 11.双 12 考验. 导读:随着 K8s 不断 ...

  7. 使用 SLF4J + LogBack 构建日志系统(转)

    转载自:http://www.cnblogs.com/mailingfeng/p/3499436.html 上次我们讨论了如何选择一个好的开源日志系统方案,其中的结论是:使用 SLF4J + LogB ...

  8. 常见java日志系统的搭配详解:关于slf4j log4j log4j2 logback jul jcl commons-logging jdk-logging

    先看一张图: 是不是有点晕, 晕就对了.这个仅仅是 slf4j 的情况,实际上, 我们不仅要接触到 slf4j ,有时候还会接触其他的日志系统.且看下文分解. 1 直接使用各个日志系统 1.1 直接使 ...

  9. SLF4J日志系统在项目导入时频现的问题

    一.概述 近期在导入一个已有的项目时,日志系统出现了一个问题.错误信息如下: SLF4J问题 SLF4J: Failed to load class "org.slf4j.impl.Stat ...

随机推荐

  1. CVE-2016-1240 Tomcat 服务本地提权漏洞

    catalogue . 漏洞背景 . 影响范围 . 漏洞原理 . 漏洞PoC . 修复方案 1. 漏洞背景 Tomcat是个运行在Apache上的应用服务器,支持运行Servlet/JSP应用程序的容 ...

  2. ubuntu下载工具uget和aria2

    一直想在ubuntu下找到个和迅雷差不多的下载工具.在网上找到了. 这篇文章完全是抄袭整理网上的. 我的系统版本是ubuntu14.04. 1.安装uget和aria2 sudo apt-get in ...

  3. HTTP Request Method共计15种

    更多信息可参考http://tools.jb51.net/table/http_request_method

  4. Beta阶段测试报告

    前端测试计划 具体测试项如下: 注册测试 登录测试 忘记密码测试 一次登录后自动登录测试 退出登录测试 编辑资料测试 查看好友测试 搜索好友测试 添加好友测试 获取当前正在游戏的房间测试 创建房间测试 ...

  5. 加密算法中BASE64、MD5、SHA、HMAC等之间的区别

    http://blog.csdn.net/lplj717/article/details/51828692 根据项目需要了解了一下几种加密算法(参考其他博客),内容简要介绍BASE64.MD5.SHA ...

  6. java -- 容易放错的误区

    1.按值传递 和 引用传递 (基本类型包括基本类型的包装类 或者 字符串类型 传递的是 副本 并不会改变原来的值)||  如果是引用类型 传递的是地址,会改变原来的值. public class T ...

  7. Web jquery表格组件 JQGrid 的使用 - 从入门到精通 开篇及索引

    因为内容比较多,所以每篇讲解一些内容,最后会放出全部代码,可以参考.操作中总会遇到各式各样的问题,个人对部分问题的研究在最后一篇 问题研究 里.欢迎大家探讨学习. 代码都经过个人测试,但仍可能有各种未 ...

  8. Windows下LATEX排版论文攻略—CTeX、JabRef使用介绍

    Windows下LATEX排版论文攻略—CTeX.JabRef使用介绍 一.工具介绍 TeX是一个很好排版工具,在学术界十分流行,特别是数学.物理学和计算机科学界. CTeX是TeX中的一个版本,指的 ...

  9. System.Web.Http.Cors配置跨域访问的两种方式

    System.Web.Http.Cors配置跨域访问的两种方式 使用System.Web.Http.Cors配置跨域访问,众多大神已经发布了很多文章,我就不在详细描述了,作为小白我只说一下自己的使用心 ...

  10. ASP.MVC时间类型json数据处理

    服务端返回DateTime属性如果用自带的json方法返回的数据如下: 有2种办法解决一种是采用服务端解决方案,一种是使用前端解决方案 1.前端解决方案 第一步:对Date进行扩展 // 对Date的 ...