log4j是Apache的一個開源項目,陪伴了咱們多年,可是如今已經不更新了。官網原文以下:java
Log4j 1.x has been widely adopted and used in many applications. However, through the years development on it has slowed down. It has become more difficult to maintain due to its need to be compliant with very old versions of Java and became End of Life in August 2015. Its alternative, SLF4J/Logback made many needed improvements to the framework. So why bother with Log4j 2? Here are a few of the reasons.web
一、log4j支持.properties或xml這兩種文件類型的配置文件。spring
二、log4j只須要引入一個jar包便可:apache
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
三、.properties配置文件屬性tomcat
### 設置根logger###
log4j.rootLogger = debug,stdout,D,E
### 輸出信息到控制檯###
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
### 輸出DEBUG 級別以上的日誌到=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
### 輸出ERROR 級別以上的日誌到=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
根Logger:log4j.rootLogger = [ level ] , appenderName, appenderName2服務器
level:日誌級別,若是級別設置爲INFO,則優先級大於等於INFO級別的日誌信息將被輸出,小於該級別的不會被輸出。mvc
appenderName:日誌信息輸出目的地,能夠是控制檯,能夠是文件。app
配置log輸出目的地ide
org.apache.log4j.ConsoleAppender:輸出到控制檯佈局
org.apache.log4j.FileAppender:文件
org.apache.log4j.DailyRollingFileAppender:天天產生一個文件
org.apache.log4j.RollingFileAppender:文件大小到達指定尺寸時產生一個新文件
選項
Append = false:默認值是true,將日誌追加到文件的最後,false是指將新的日誌消息覆蓋文件原有的內容
Threshold = INFO:指定日誌輸出的最低層次,這裏INFO及以上層次的日誌都將被輸出
filter.F=org.apache.log4j.varia.LevelRangeFilter:這個是對Threshold的一個補充,若是Threshold配置成DEBUG,則debug.log會記錄debug、info、error等全部級別大於debug的日誌
這樣在經過日誌定位問題的時候有點雜亂,咱們想debug、info、error的日誌分別記錄到對應的文件中該怎麼辦?
filter.F.LevelMin=DEBUG
filter.F.LevelMax=DEBUG
這樣就能經過該文件裏記錄的日誌級別(最大和最小的都是debug,則只能記錄debug)
layout = org.apache.log4j.PatternLayout:日誌信息的輸出格式,PatternLayout指能夠靈活地指定佈局模式
layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}:配置具體的日誌格式
%d:輸出日誌時間點的日期或時間,也能夠指定格式,如:%d{yyyy-MM-dd HH:mm:ss}
%c:輸出日誌信息所屬的類目,一般就是所在類的全名
%t:輸出產生該日誌事件的線程名
%L:輸出代碼中的行號
%n:輸出一個回車換行符
一、pom.xml
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
log4j只須要引入這一個jar
二、log4j.properties的配置
### 設置根logger###
log4j.rootLogger = debug,stdout,D,E
### 輸出信息到控制檯###
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 = [%d{yyyyMMdd HH:mm:ssSSS\}%-5p]{%m} %l%n
### 輸出DEBUG 級別以上的日誌到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/debug.log
log4j.appender.D.Append = true
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = [%d{yyyyMMdd HH:mm:ssSSS\}%-5p]{%m} %l%n
log4j.appender.D.filter.F=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.D.filter.F.LevelMin=DEBUG
log4j.appender.D.filter.F.LevelMax=DEBUG
### 輸出ERROR 級別以上的日誌到=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.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = [%d{yyyyMMdd HH:mm:ssSSS\}%-5p]{%m} %l%n
log4j.appender.E.filter.F=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.E.filter.F.LevelMin=ERROR
log4j.appender.E.filter.F.LevelMax=ERROR
該配置文件我有意放在src目錄下,項目啓動的時候能直接查找到。後面會專門介紹log4j配置文件的加載
三、測試類:
package cd.com.log4j; import org.apache.log4j.Logger; public class App { private static Logger logger = Logger.getLogger(App.class); public static void main( String[] args ) { //日誌記錄 logger.debug("debug: hello log4j"); logger.info("info: hello log4j"); logger.warn("warn: hello log4j"); logger.error("error: hello log4j"); } }
四、控制檯輸出:
[20170524 10:38:02401DEBUG]{debug: hello log4j} cd.com.log4j.App.main(App.java:12) [20170524 10:38:02401INFO ]{info: hello log4j} cd.com.log4j.App.main(App.java:13) [20170524 10:38:02401WARN ]{warn: hello log4j} cd.com.log4j.App.main(App.java:14) [20170524 10:38:02401ERROR]{error: hello log4j} cd.com.log4j.App.main(App.java:15)
五、輸出的日誌文件:
6.日誌內容:
經過前面的配置,咱們能夠將不一樣級別的日誌輸出到對應的文件中
對於不一樣的應用服務器(或者web服務器)來講,classloader的層次不盡相同。這裏以最簡單的tomcat來講,若是你的應用是部署到 tomcat下的,使用log4j配置文件的順序就是$TOMCAT_HOME/lib/log4j.xml或者log4j.properties;你本身web應用/WEB-INF/classes(或者lib)/log4j.xml
log4j的jar默認就是到src目錄下去找log4j.properties 這個配置文件的。可是若是你沒有將這個文件放在src下的。這個狀況下就須要本身去加載了
我這裏的工程是基於SpringMVC模式的
一、pom.xml:導入的仍是跟上面同樣的jar包
2.須要在web.xml中配置log4j.properties,這樣在容器啓動的時候能夠加載到log4j的配置文件
三、測試類:
package com.cd.mvc.controller; import javax.servlet.ServletRequest; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.EnvironmentAware; import org.springframework.core.env.Environment; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.cd.mvc.bean.Product; @Controller public class DemoController implements EnvironmentAware { private Environment environment = null; @Autowired private Product product; static Logger logger = Logger.getLogger(DemoController.class); @RequestMapping(value = "index/{id}", method = RequestMethod.GET,params="age=14") public String index(@PathVariable int id,ServletRequest request,Model model) { logger.info("info id =" + id); logger.warn("warn id =" + id); logger.error("error id =" + id); // String age = (String)request.getParameter("age"); // System.out.println(age); // this.product.sayHello(); // model.addAttribute("title","hello hangzhou"); return "index"; } @Override public void setEnvironment(Environment environment) { this.environment = environment; } }
四、使用postman進行訪問:
五、控制檯打印信息:
這樣咱們介紹了普通的JAVA工程和web工程兩種方式集成log4j,後面一種應該是比較常見的場景:能夠本身配置log4j.properties的存放位置,只須要在web.xml中正確引用便可。
因爲Junit測試很是方便,也是開發過程當中必不可少的一個環節。可是這種整合起來比較複雜,因爲spring+log4j的整合,是在web.xml中配置的,如上一個示例所示。在tomcat啓動時,spring會主動去加載log4j的配置文件。而Junit測試是不須要啓動tomcat的,因此會形成文件找到的報錯。
這裏提供兩種方法:
一、將配置文件放在src下面,log4j的jar包會默認從src目錄下查找:
這裏配置文件是放在src/main/resources下的,log4j的jar包會自動到該目錄下尋找。
二、Junit測試類:
package com.cd.mvc.controller; import java.io.IOException; import org.apache.log4j.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:META-INF/spring/springContext.xml") public class TestLog4j { private final static Logger logger = Logger.getLogger(TestLog4j.class); @Test public void test() throws IOException { logger.info("info layout"); logger.warn("warn layout"); logger.error("error layout"); } }
該測試類中的兩個註解都是跟Junit相關的,與log4j無關。這裏咱們沒有手動去加載log4j的配置文件。
三、測試結果:
[20170524 15:57:04030INFO ]{Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]} org.springframework.test.context.support.AbstractTestContextBootstrapper.getDefaultTestExecutionListenerClassNames(AbstractTestContextBootstrapper.java:256) [20170524 15:57:04038INFO ]{Could not instantiate TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttributeSource]} org.springframework.test.context.support.AbstractTestContextBootstrapper.instantiateListeners(AbstractTestContextBootstrapper.java:204) [20170524 15:57:04039INFO ]{Could not instantiate TestExecutionListener [org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttribute]} org.springframework.test.context.support.AbstractTestContextBootstrapper.instantiateListeners(AbstractTestContextBootstrapper.java:204) [20170524 15:57:04040INFO ]{Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@79560ca4, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@582138, org.springframework.test.context.support.DirtiesContextTestExecutionListener@19ece3b5]} org.springframework.test.context.support.AbstractTestContextBootstrapper.getTestExecutionListeners(AbstractTestContextBootstrapper.java:182) [20170524 15:57:04130INFO ]{Loading XML bean definitions from class path resource [META-INF/spring/springContext.xml]} org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:317) [20170524 15:57:04236INFO ]{Refreshing org.springframework.context.support.GenericApplicationContext@602f958: startup date [Wed May 24 15:57:04 CST 2017]; root of context hierarchy} org.springframework.context.support.AbstractApplicationContext.prepareRefresh(AbstractApplicationContext.java:582) [20170524 15:57:04297INFO ]{Loading properties file from file [D:\workspace\SpringMVC\target\classes\META-INF\log4j.properties]} org.springframework.core.io.support.PropertiesLoaderSupport.loadProperties(PropertiesLoaderSupport.java:172) [20170524 15:57:04335INFO ]{info layout} com.cd.mvc.controller.TestLog4j.test(TestLog4j.java:23) [20170524 15:57:04336WARN ]{warn layout} com.cd.mvc.controller.TestLog4j.test(TestLog4j.java:24) [20170524 15:57:04336ERROR]{error layout} com.cd.mvc.controller.TestLog4j.test(TestLog4j.java:25) [20170524 15:57:04339INFO ]{Closing org.springframework.context.support.GenericApplicationContext@602f958: startup date [Wed May 24 15:57:04 CST 2017]; root of context hierarchy} org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:987)
控制檯上打印了info以上級別日誌,有spring啓動過程當中的日誌,有業務中輸出的日誌。
一、Junit測試類:
package com.cd.mvc.controller; import java.io.IOException; import org.apache.log4j.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.Log4jConfigurer; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:META-INF/spring/springContext.xml") public class TestLog4j { private final static Logger logger = Logger.getLogger(TestLog4j.class); @Test public void test() throws IOException { Log4jConfigurer.initLogging("classpath:META-INF/log4j.properties"); logger.info("info layout"); logger.warn("warn layout"); logger.error("error layout"); } }
二、這裏比示例1多了一行用紅色標記的代碼,做用就是主動去查找log4j.properties,該配置文件不在默認的src目錄下,log4j的jar包沒法找到。
三、測試結果:
因爲這種方式中配置文件靈活可配置,建議採用這種方式進行單元測試。