Intellij idea中使用SLF4J+log4j做日志记录

来源:互联网 发布:淘宝客怎么注册不了了 编辑:程序博客网 时间:2024/05/20 16:32

Intellij idea中使用SLF4J+log4j做日志记录

一、  简介

SLF4J (Simple Logging Facade for Java) 不是具体的日志解决方案,它只服务于各种各样的日志系统。按照官方的说法,SLF4J是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志系统。
实际上,SLF4J所提供的核心API是一些接口以及一个LoggerFactory的工厂类。从某种程度上,SLF4J有点类似JDBC,不过比JDBC更简单,在JDBC中,你需要指定驱动程序,而在使用SLF4J的时候,不需要在代码中或配置文件中指定你打算使用那个具体的日志系统。如同使用JDBC基本不用考虑具体数据库一样,SLF4J提供了统一的记录日志的接口,只要按照其提供的方法记录即可,最终日志的格式、记录级别、输出方式等通过具体日志系统的配置来实现,因此可以在应用中灵活切换日志系统。

二 应用程序中使用方法及配置

1 先在idea中用新建一个maven的空项目,建好的项目结构如图:


部分文件是后面加的,结构就是这样子的

 2 我们添加一个class(testDemo.class),并添加main方法,代码如下:

import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * Created by hqj on 2017/7/25. */public class testDemo {    private static Logger logger = LoggerFactory.getLogger(testDemo.class);    public static void main(String[] args) {        System.out.println("This is println message. yeah");        // 记录debug级别的信息        logger.debug("This is debug message.");        // 记录info级别的信息        logger.info("This is info message.");        // 记录error级别的信息        logger.error("This is error message.");    }}

3 添加相应的包,在pom.xml中添加相应的依赖,然后点击右下角的import changes 即可自动导入相应的包

pom.xml添加的内容如下:

<dependencies>    <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->    <dependency>        <groupId>org.slf4j</groupId>        <artifactId>slf4j-api</artifactId>        <version>1.7.2</version>    </dependency>    <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->    <dependency>        <groupId>org.slf4j</groupId>        <artifactId>slf4j-log4j12</artifactId>        <version>1.7.2</version>    </dependency></dependencies>

4 在src>main>resources下添加 log4j.properties文件,内容如下:

### 设置###log4j.rootLogger = debug,stdout,D,E,I### 输出信息到控制抬 ###log4j.appender.stdout = org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.Target = System.outlog4j.appender.stdout.layout = org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n### 输出DEBUG 级别以上的日志到=E://logs/error.log ###log4j.appender.D = org.apache.log4j.DailyRollingFileAppenderlog4j.appender.D.File = E://logs/log.loglog4j.appender.D.Append = truelog4j.appender.D.Threshold = DEBUGlog4j.appender.D.layout = org.apache.log4j.PatternLayoutlog4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n### 输出ERROR 级别以上的日志到=E://logs/error.log ###log4j.appender.E = org.apache.log4j.DailyRollingFileAppenderlog4j.appender.E.File =E://logs/error.loglog4j.appender.E.Append = truelog4j.appender.E.Threshold = ERRORlog4j.appender.E.layout = org.apache.log4j.PatternLayoutlog4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n### 输出INFO 级别以上的日志到=E://logs/error.log ###log4j.appender.I = org.apache.log4j.DailyRollingFileAppenderlog4j.appender.I.File =E://logs/info.loglog4j.appender.I.Append = truelog4j.appender.I.Threshold = INFOlog4j.appender.I.layout = org.apache.log4j.PatternLayoutlog4j.appender.I.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

其中路径部分可更改,

5 启动程序看是否能输出日志,启动时程序会弹出让配置启动类,设为testDemo即可,程序正常启动,且在相应的目录可以看到产生了日志文件。

三 spring+mvc web项目使用及配置方法

1 新建好一个 spring mvc web项目,过程略,可参见另一篇 去看看

2 在pom.xml中添加相应的依赖,然后点击右下角的import changes导入相应的包,加的内容如下:

<dependency>      <groupId>org.slf4j</groupId>      <artifactId>slf4j-api</artifactId>      <version>1.7.2</version>    </dependency>    <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->    <dependency>      <groupId>org.slf4j</groupId>      <artifactId>slf4j-log4j12</artifactId>      <version>1.7.2</version>    </dependency>

3 在web.xml中加入如下内容:

<context-param>    <param-name>log4jConfigLocation</param-name>    <!--<param-value>classpath:/log4j/log4j.xml</param-value>-->    <param-value>/WEB-INF/config/log4j.properties</param-value>  </context-param>  <!-- 加载log4j配置文件 -->  <listener>    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>  </listener>
如上内容中有一个注释了的,原来是按这么写的,发现不行,改成 <param-value>/WEB-INF/config/log4j.properties</param-value> 这样即可

4 在web-inf下建config文件夹,再在config下添加log4j.properties文件,内容如下:

### 设置###log4j.rootLogger = debug,stdout,D,E,I### 输出信息到控制抬 ###log4j.appender.stdout = org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.Target = System.outlog4j.appender.stdout.layout = org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n### 输出DEBUG 级别以上的日志到=E://logs/error.log ###log4j.appender.D = org.apache.log4j.DailyRollingFileAppenderlog4j.appender.D.File = E://logs/log.loglog4j.appender.D.Append = truelog4j.appender.D.Threshold = DEBUGlog4j.appender.D.layout = org.apache.log4j.PatternLayoutlog4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n### 输出ERROR 级别以上的日志到=E://logs/error.log ###log4j.appender.E = org.apache.log4j.DailyRollingFileAppenderlog4j.appender.E.File =E://logs/error.loglog4j.appender.E.Append = truelog4j.appender.E.Threshold = ERRORlog4j.appender.E.layout = org.apache.log4j.PatternLayoutlog4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n### 输出INFO 级别以上的日志到=E://logs/error.log ###log4j.appender.I = org.apache.log4j.DailyRollingFileAppenderlog4j.appender.I.File =E://logs/info.loglog4j.appender.I.Append = truelog4j.appender.I.Threshold = INFOlog4j.appender.I.layout = org.apache.log4j.PatternLayoutlog4j.appender.I.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

5 至引配置完成,启动tomcat,运行程序,发现日志如期输出。

上面两个demo都能正常运行,idea版本为IntelliJ IDEA 2017.1.4 x64。本篇只是测试日志能否正常记录,代码及配置可以再优化,后续再修改。

四 SLF4J对比Log4J,logback和java.util.Logging的优势


正如我之前说的,在你的代码中使用SLF4J写日志语句的主要出发点是使得你的程序独立于任意特定的日志类库,依赖于特定类可能需要不同与你已有的配置,并且导致更多维护的麻烦。但除此之外,还要一个SLF4J API的特性使得我坚持使用SLF4J而抛弃我长期间钟爱的Lof4j的理由,是被称为占位符(place holder),在代码中表示为“{}”的特性。占位符是一个非常类似于在String的format()方法中的%s,因为它会在运行时被某个提供的实际字符串所替换。这不仅降低了你代码中字符串连接次数,而且还节省了新建的String对象。即使你可能没需要那些对象,但这个依旧成立,取决于你的生产环境的日志级别,例如在DEBUG或者INFO级别的字符串连接。因为String对象是不可修改的并且它们建立在一个String池中,它们消耗堆内存( heap memory)而且大多数时间他们是不被需要的,例如当你的应用程序在生产环境以ERROR级别运行时候,一个String使用在DEBUG语句就是不被需要的。通过使用SLF4J,你可以在运行时延迟字符串的建立,这意味着只有需要的String对象才被建立。而如果你已经使用log4j,那么你已经对于在if条件中使用debug语句这种变通方案十分熟悉了,但SLF4J的占位符就比这个好用得多。

这是你在Log4j中使用的方案,但肯定这一点都不有趣并且降低了代码可读性因为增加了不必要的繁琐重复代码(boiler-plate code):

if (logger.isDebugEnabled()) {    logger.debug("Processing trade with id: " + id + " symbol: " + symbol);}

另一方面,如果你使用SLF4J的话,你可以得到在极简洁的格式的结果,就像以下展示的一样:

logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);

在SLF4J,我们不需要字符串连接而且不会导致暂时不需要的字符串消耗。取而代之的,我们在一个以占位符和以参数传递实际值的模板格式下写日志信息。你可能会在想万一我有很个参数怎么办?嗯,那么你可以选择使用变量参数版本的日志方法或者用以Object数组传递。这是一个相当的方便和高效方法的打日志方法。记住,在生产最终日志信息的字符串之前,这个方法会检查一个特定的日志级别是不是打开了,这不仅降低了内存消耗而且预先降低了CPU去处理字符串连接命令的时间。这里是使用SLF4J日志方法的代码,来自于slf4j-log4j12-1.6.1.jar中的Log4j的适配器类Log4jLoggerAdapter。


public void debug(String format, Object arg1, Object arg2) {    if (logger.isDebugEnabled()) {        FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);        logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());    }}

同时,我们也很值得知道打日志是对应用程序的性能有着很大影响的,在生产环节上只进行必要的日志记录是我们所建议的。


--- end ---



原创粉丝点击