Java日誌相關記錄 (Jul jcl log4j log4j2 Logback SLF4J)

1、寫在前面 java

在java 中實現記錄日誌的方式有不少種
1. 最初的方式,就是system.print.out ,err 這樣直接在控制檯打印消息,缺點太多了,這樣與業務邏輯無關的代碼會變得更多,不能按日誌等及輸出,以及那些不輸出等。
2. JUL,java util logging在jdk的java.util.logging包中,也叫jkdLog或者jdk14log; 在JDK 1.4 版本以後,java提供了日誌的API ,能夠往文件中寫日誌了,最方便不須要第三方包,其實際使用人較少。
3. log4j , 最強大的記錄日誌的方式。 能夠經過配置 .properties 或是 .xml 的文件, 配置日誌的目的地,格式等等,基於老的jdk性能不高,該項目如今已經中止維護,可是用的人仍是最多的。
4. Log4j2 該項目是log4j的升級版,性能較好,也吸取了logback等日誌記錄組件的優勢。
5. commons-logging是一個日誌接口,最綜合和常見的日誌記錄方式, 常常是和log4j或者log4j2 結合起來使用。
6. Slf4j也是一個日誌接口,最多見的是和logback一塊兒使用。
7. 日誌等級其實最經常使用的就是這四個等級(debug,info,warn,error)。 apache

2、JUL(java util logger) api

使用java 自帶的logger最方便的做用提無需引入第三方包
直接上代碼: app

package com.xxx.test;
import java.io.IOException;
import java.util.Date;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

public class TestLogJava {
    public static void main(String[] args) throws IOException{
        Logger log = Logger.getLogger("tesglog");
        log.setLevel(Level.ALL);
        FileHandler fileHandler = new FileHandler("testlog.log");
        fileHandler.setLevel(Level.ALL);
        fileHandler.setFormatter(new LogFormatter());
        log.addHandler(fileHandler);
        log.info("This is test java util log"); 
        log.warning("warning .........");
        log.log(Level.FINE, "fine...");
        log.finer("finer ....");
    }
}
 
class LogFormatter extends Formatter {
    @Override
    public String format(LogRecord record) {
        Date date = new Date();
        String sDate = date.toString();
        return "[" + sDate + "]" + "[" + record.getLevel() + "]"
                + record.getClass() + record.getMessage() + "\n";
    }
}



Java util logger使用的日誌級別:SEVERE(最高值),WARNING,INFO,CONFIG,FINE,FINER,FINEST(最低值)以及OFF和ALL
先通地Logger工廠得到一個log實例,日誌記當格是默認是xml 使用前最好先本身格式化本身所要的格式(上面的LogFormatter就是自定義格式)。log的Handler有許多可使用常見是寫到文件也就是FileHandler。
使用步驟:new 一個FileHandler 實例,設定fileHandler的等級和格式,並添加到log實例上,而後就是直接使用log.info()寫入了。 eclipse

3、JCL(Jakarta commons logger) ide

說的是java 通用日誌,實際上是apache出品的通用日誌接口,是一個接口。
提供的是一個日誌(Log)接口(interface),同時兼顧輕量級和不依賴於具體的日誌實現工具。它提供給中間件/日誌工具開發者一個簡單的日誌操做抽象,容許程序開發人員使用不一樣的具體日誌實現工具。
JCL有兩個基本的抽象類:Log(基本記錄器)和LogFactory(負責建立Log實例)。當commons-logging.jar被加入到 CLASSPATH以後,它會合理地猜想你想用的日誌工具,而後進行自我設置,用戶根本不須要作任何設置。默認的LogFactory是按照下列的步驟去發現並決定那個日誌工具將被使用的(按照順序,尋找過程會在找到第一個工具時停止):
   1. 尋找當前factory中名叫org.apache.commons.logging.Log配置屬性的值
   2. 尋找系統中屬性中名叫org.apache.commons.logging.Log的值
   3. 若是應用程序的classpath中有log4j,則使用相關的包裝(wrapper)類(Log4JLogger)
   4. 若是應用程序運行在jdk1.4的系統中,使用相關的包裝類(Jdk14Logger)
   5. 使用簡易日誌包裝類(SimpleLog)
org.apache.commons.logging.Log的具體實現有以下:
-org.apache.commons.logging.impl.Jdk14Logger 使用JDK1.4。
-org.apache.commons.logging.impl.Log4JLogger 使用Log4J。
-org.apache.commons.logging.impl.LogKitLogger 使用 avalon-Logkit。
-org.apache.commons.logging.impl.SimpleLog common-logging自帶日誌實現類。它實現了Log接口,把日誌消息都輸出到系統錯誤流System.err 中。 
-org.apache.commons.logging.impl.NoOpLog common-logging自帶日誌實現類。它實現了Log接口。 其輸出日誌的方法中不進行任何操做。 工具

package com.xxx.test;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.*;
public class TestCommonLog {
	private static Log log = LogFactory.getLog(TestCommonLog.class);
	public static void main(String[] args) {
		log.debug("debug ......");
		log.info("info ......");
		log.warn("warn ......");
		log.error("error ......");
		log.fatal("fatal ......");
	}
}


4、log4j(log4j版本1) 性能

Log4j是java開發用得最多最多見的日誌組件,這個是組件,是有完整的實現。能夠完整的獨立使用。
直接上代碼: spa

Log4j.properties debug

### \u8BBE\u7F6E###
log4j.rootLogger = debug,stdout,D,E

### \u8F93\u51FA\u4FE1\u606F\u5230\u63A7\u5236\u62AC ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### \u8F93\u51FADEBUG \u7EA7\u522B\u4EE5\u4E0A\u7684\u65E5\u5FD7\u5230=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### \u8F93\u51FAERROR \u7EA7\u522B\u4EE5\u4E0A\u7684\u65E5\u5FD7\u5230=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n



Log4jTest.java

package com.xxx.test;
import org.apache.log4j.Logger;
public class Log4jTest {
	private static Logger logger = Logger.getLogger(Log4jTest.class);
	public static void main(String args[]) {
		// 記錄debug級別的信息
		logger.debug("debug");
		// 記錄info級別的信息
		logger.info("info");
		// 記錄error級別的信息
		logger.error("error");
	}
}



5、log4j2使用

Log4j2是log4j的重構升級版,他改進了log4j性能和不足,吸收了logback優勢
不說了直接上代碼:

Log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
	<Appenders>
		<Console name="Console" target="SYSTEM_OUT">
			<PatternLayout pattern="%m%n" />
		</Console>
	</Appenders>
	<Loggers>
		<Root level="DEBUG">
			<AppenderRef ref="Console" />
		</Root>
	</Loggers>
</Configuration>


Log4j2Test.java

package com.xxx.test;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; 
public class Log4j2Test {
	private static Logger logger = LogManager.getLogger(Log4j2Test.class);
	public static boolean hello() {
        logger.entry();   //trace級別的信息,單獨列出來是但願你在某個方法或者程序邏輯開始的時候調用,和logger.trace("entry")基本一個意思
        logger.error("Did it again!");   //error級別的信息,參數就是你輸出的信息
        logger.info("我是info信息");    //info級別的信息
        logger.debug("我是debug信息");
        logger.warn("我是warn信息");
        logger.fatal("我是fatal信息");
        logger.log(Level.DEBUG, "我是debug信息");   //這個就是制定Level類型的調用:誰閒着沒事調用這個,也不必定哦!
        logger.exit();    //和entry()對應的結束方法,和logger.trace("exit");一個意思
        return false;
    }
	public static void main(String[] args) {
		hello();
	}
}

log4j2在沒有任何配置的狀況下文件時會自動使用默認的配置:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Root level="error">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>


該配置只有一個Appender:Console,目標是SYSTEM_OUT,即日誌內容,都會打印在eclipse控制檯上。Root Logger的級別是error,即:全部error及以上級別的日誌纔會記錄。(注:日誌級別順序爲 TRACE < DEBUG < INFO < WARN < ERROR < FATAL ),因此最終只有2日誌會輸出(error,fatal)


再來Log4j2的詳細一點的配置

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="OFF">
	<Appenders>
		<Console name="Console" target="SYSTEM_OUT">
			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
		</Console>

		<File name="ERROR" fileName="logs/error.log">
			<ThresholdFilter level="error" onMatch="ACCEPT"
				onMismatch="DENY" />
			<PatternLayout
				pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n" />
		</File>

		<RollingFile name="RollingFile" fileName="logs/app.log"
			filePattern="log/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
			<PatternLayout
				pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n" />
			<SizeBasedTriggeringPolicy size="50MB" />
		</RollingFile>

		<RollingFile name="ROLLING" fileName="d:/logs/howsun.log"
			filePattern="d:/logs/howsun_%d{yyyy-MM-dd}_%i.log">
			<PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
			<Policies>
				<TimeBasedTriggeringPolicy modulate="true"
					interval="24" />
				<SizeBasedTriggeringPolicy size="51200 KB" />
			</Policies>
			<DefaultRolloverStrategy max="20" />
		</RollingFile>

		<properties>
			<property name="filenameLog">logs/payPlatform.log</property>
		</properties>

		<!-- 定義後臺文檔日誌記錄 -->
		<RollingFile name="RollingFile" fileName="${filenameLog}"
			filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
			<PatternLayout>
				<Pattern>%d{yyyy-MM-dd HH:mm:ss} [%p] [%t] %c{1}.%M(%L) | %m%n
				</Pattern>
			</PatternLayout>
			<Policies>
				<!-- 定義log文件封存的週期 -->
				<TimeBasedTriggeringPolicy interval="1"
					modulate="true" />
				<SizeBasedTriggeringPolicy size="100 MB" />
			</Policies>
			<DefaultRolloverStrategy fileIndex="max" max="2" />
		</RollingFile>

	</Appenders>
	<Loggers>
		<Root level="DEBUG">
			<AppenderRef ref="Console" />
			<appender-ref ref="ROLLING" />
			<appenderRef ref="RollingFile" />
		</Root>
	</Loggers>
</Configuration>



6、SLF4J與Logback 

SLF4J全名Simple Logging Facade for Java
不是具體的日誌解決方案,它只服務於各類各樣的日誌系統。按照官方的說法,SLF4J是一個用於日誌系統的簡單Facade,容許最終用戶在部署其應用時使用其所但願的日誌系統。
SLF4J同apache的commons-logger同樣,都是供示一個簡單的接口,不是一個完格的日誌解決方案他通常須要和其它日誌系統進行配合使用。
SLF4J建立項目在包中引入SLF4J的核心接口slf4j-api.jar包
上代碼:

package com.xxx.test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogbackTest {
	private static Logger logger = LoggerFactory.getLogger(LogbackTest.class);
	public static void main(String[] args) {
		System.out.println("-----");
		logger.trace("trace");  
        logger.debug("debug");  
        logger.info("info");  
        logger.warn("warn");  
        logger.error("error");
	}
}



若是沒有引入其它包,是打印不出日誌的,


這裏必須在再引入一個現實的包可使用slf4j-simple.jar,這樣slf4j-api會調用slf4j-simple.jarsimple現實(所有打印在console上),也可使用slf4j-nop.jar就是無任何操做的實現。
同理,也能夠在jdk1.4上使用slf4j-jdk14.jar包來使用jdk14logger的實現,也可以使用slf4j-jcl.jarJakarta commons logger的實現,雖然他自身也是一個通用日誌接口),一樣可使用slf4j-logj12.jar的實現了。只是在使用其它實現是須要加入其它相應日誌系統的jar 包並同時作好相應日誌系統的配置,例使用了slf4j-log4j12.jar則還須要加入log4j-1.2.7.jar 包,而且在寫好相應的log4j.properties配置文件。

SLF4J這種機制還能夠把原來用的不是slf4j這種日誌接口的直接轉換成slf4j。例原來使用的是commons-logging能夠把原來的commons-logging.jar包刪除,把jcl-over-slf4j.jar添加到項目便可。

提到slf4j就不得不提一下logback

Logback同也是由log4j主創人創立,slf4j也是他搞的。改寫了log4j的核心提升了性能,意在替換log4j(指log4j-v1)。logback項目主要有三個部分core, classic, access, corelogback的核心,classicslf4japi的實現,而access則是配使servlet容器配合提供http訪問記錄。

使用同上,須要加入slf4j-api.jarlogback-core.jar,logback-classic.jar,logback-access.jar

Slf4jLogbackTest.java

package com.xxx.test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogbackTest {
	private static Logger logger = LoggerFactory.getLogger(LogbackTest.class);
	public static void main(String[] args) {	
	 logger.trace("======trace");  
        logger.debug("======debug");  
        logger.info("======info");  
        logger.warn("======warn");  
        logger.error("======error");
	}
}



Logback.xml

<?xml version="1.0" encoding="UTF-8" ?>
<configuration debug="true">
  <appender name="STDOUT"
    class="ch.qos.logback.core.ConsoleAppender">
    <!-- encoders are assigned by default the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>
  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>



這個是logback的配置文件,其實不配logback.xml也是能夠的,程序會自動加載一個默認BasicConfigurator的配置,最 小化 配置 由 一個 關聯 到 根 logger ConsoleAppender 組成。 輸出用模式爲%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}- %msg%n 的 PatternLayoutEncoder 進行格式化,根 logger 默認級別是 DEBUG
說到這裏也說一下logback讀取配置文件規則:,先讀取logback-test.xml,沒有則查找logback.xml若是也沒有就加載BasicConfigurator配置。

寫在最後:

jdkLog就是JUL,在項目實際中用得較少,小的項目中都是直接使用log4j或者log4j2,或都使用commons-logging再配合log4j或者log4j2。也有許多項目直接使用slf4j+logback
通常建議是使用commons-logging+log4j或者slf4j+logback吧,若是項目的其它組件充許要不直接上log4j2也是能夠的。

相關文章
相關標籤/搜索