Spring在JavaWeb工程中整合log4j
在《【Spring】Spring3.0.5的下載、配置與Helloworld》(點擊開啟連結)一文各位已經可能看到了。如果Spring不整合log4j直接啟動,則會出現如下關於Spring整合log4j的警告。這個挺煩人的,一方面自己提倡高內聚,低耦合,另一方面,自己沒有整合log4j就提出警告。我們程式猿寫出來的程式就叫做“耦合”,它Spring就叫做“整合”。好吧!你只能同時搞明白,log4j是個什麼鬼東西,Spring怎麼整合log4j,兩個問題:
log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader). log4j:WARN Please initialize the log4j system properly.
由於此前介紹的都是Spring在Java工程中簡單樣本,log4j必須在JavaWeb工程中運行才有意義,你同時還要搞明白Spring怎麼在JavaWeb工程上面運行,Spring怎麼在JavaWeb工程中整合log4j。
一、Spring與Log4j的下載
1、你首先要有這兩個JavaWeb組件的jar包吧?不然怎麼搞出來?Spring在《【Spring】Spring3.0.5的下載、配置與Helloworld》(點擊開啟連結)一文中已經講過怎麼下載了。Log4j則開啟Apache的官網(點擊開啟連結)如,選擇log4j-1.2.17.zip(Windows)或者log4j-1.2.17.tar.gz(Linux)。同樣是Apache的東西,在一些高版本的Tomcat中還整合了這個東西,當然,你最好還是在WEB-INF\lib目錄下補上這個包,以致於你的工程在所有Tomcat都能跑。
2、在Eclipse for JavaEE中建立一個名為SpringLog4j的Dynamic Web Project,還在解壓之後,把spring-framework-3.0.5.RELEASE-dependencies的所有東西與spring-framework-3.0.5.RELEASE\dist中的所有Jar包,不包括那個LIBD檔案,apache-log4j-1.2.17下的log4j-1.2.17.jar,拷貝到WEB\lib檔案夾。
3、之後你的Eclipse for JavaEE如下所示。WEB-INF目錄下的Web.xml、applicationContext.xml、log4j.properties與根目錄下的Log4j.jsp是一會兒我們要寫的東西。
二、Spring與Log4j的配置
1、Web.xml
首先是這個關於JavaWeb的工程的總配置位置。我們要在裡面聲明要使用Spring與Log4j。值得注意的Log4j的配置必須在Spring配置之前,否則如果先啟動Spring,那個必須整合Log4j才不吐警告的Spring,由於Log4j還沒有啟動,找不到Spring,又會在任性地吐警告。當然,你設定那些什麼優先順序也行,不過,先啟動的直接放前面,這個檔案不是更好看嗎?
org.springframework.web.util.Log4jConfigListenerlog4jConfigLocation/WEB-INF/log4j.propertiesorg.springframework.web.context.ContextLoaderListenercontextConfigLocation/WEB-INF/applicationContext.xml
2、log4j.properties
這傢伙的尾碼名是這麼長,你有什麼辦法?必須照打,都是Linux那邊帶過來的主,你看看人家Windows的設定檔的尾碼名僅僅就是ini3個字母!
#log4j.rootLogger = [ level ] , appenderName, appenderName, ...log4j.rootLogger = all, console, R#Consolelog4j.appender.console = org.apache.log4j.ConsoleAppenderlog4j.appender.console.layout = org.apache.log4j.PatternLayoutlog4j.appender.console.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n#Filelog4j.appender.R = org.apache.log4j.RollingFileAppenderlog4j.appender.R.File = c:/log.txtlog4j.appender.R.MaxFileSize = 500KBlog4j.appender.R.MaxBackupIndex = 1log4j.appender.R.layout = org.apache.log4j.PatternLayoutlog4j.appender.R.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] - %m%n
這東西還加不了中文注釋,給大家一行一行地講。#後面還僅能寫英文的東西,把我大天朝的程式猿放哪裡?我就加個中文注釋都不讓!
首先第一部分是log4j的總配置部分,all代表debug,info,error,fatal四種類型的資訊都會輸出。一般不設定為all,這裡只是為了讓大家看到效果。因為那些debug,info資訊對我們半點鐘意義沒有,還因為有很多系統內部的檔案運行都會輸出debug與info資訊刷屏、刷版。關鍵是輸出到磁碟的記錄檔會極速遞增,浪費磁碟空間。玩SQL Server的時候大家又不知道那個.ldb是多麼恐怖?
因此第一部分,一般寫成:
log4j.rootLogger = ERROR, console, R
代表僅輸出error與fatal錯誤。
之後的console,R分別代表在控制台與檔案輸出。同時在之後的代碼必須配置好這個兩輸出。
第二部分控制台#Console
首先要使用log4j特定的包,這個沒有什麼好說,最後一句指明輸出格式。一會兒大招對照輸出結果就明白怎麼回事了。
第三部分檔案#File
log4j.appender.R.File=c:/log.txt是指這個Web工程錯誤記錄檔皆輸出到c:/log.txt。不要像網上那些大神輸出一個什麼.log尾碼,關鍵是能夠直接開啟。
之後log4j.appender.R.MaxFileSize = 500KB指明這個log.txt檔案大小最多為500KB,如果超過這個大小,自動開一個新檔案,而log4j.appender.R.MaxBackupIndex=1指明此工程頂多隻能有1個這個的記錄檔。多了的話,新內容覆蓋舊內容,就像那些閉路電視攝影機一樣。
Log4j到這裡就搞完了。
3、applicationContext.xml
之後是Spring的部分,由於這次根本就沒有用Spring做任何東西,因此,這個applicationContext.xml這樣寫就行了:
能刪的我都刪了。
4、Log4j.jsp
最後是在WebContent根目錄下的Log4j.jsp。在裡面寫入如下代碼,整個程式的入口就是這個地方。
Servlet我都不搞了,就是為了讓大家直接看清楚問題的關鍵所在。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="org.apache.log4j.Logger"%><%Logger.getLogger(this.getClass()).fatal("致命錯誤!");Logger.getLogger(this.getClass()).error("出錯資訊!");Logger.getLogger(this.getClass()).info("普通訊息!");Logger.getLogger(this.getClass()).debug("調試資訊!");%>
三、運行結果
把SpringLog4j這個JavaWeb工程掛到Tomcat裡面,運行,之後在任意瀏覽器輸入http://localhost:8080/SpringLog4j/Log4j.jsp,待網頁成功載入之後,直接回到Eclipse則得到如下的運行結果,你輸入一次網址重新整理一次,則輸出一次以下結果:
同時,你的C盤,則多出一個log.txt,裡面的內容如下,可以看到,在程式啟動並執行時候,Spring的運行會吐出很多無意義的DEBUG、INFO、TRACE的資訊,對於我們來說,真正有用的最後面的四句話。因此,可以理解,為何在上面的log4j.properties(這個尾碼名又難記,又長,再次鄙視之!)的第一部分一般不寫all,唯寫ERROR,這就只輸出ERROR以上等級的錯誤,也就是ERROR與FATAL。或者寫成TRACE,輸出TRACE、ERROR與FATAL資訊。
2015-05-10 09:54:34 [org.springframework.web.context.ContextLoader]-[INFO] - Root WebApplicationContext: initialization started2015-05-10 09:54:34 [org.springframework.web.context.support.XmlWebApplicationContext]-[INFO] - Refreshing Root WebApplicationContext: startup date [Sun May 10 09:54:34 CST 2015]; root of context hierarchy2015-05-10 09:54:34 [org.springframework.beans.factory.xml.XmlBeanDefinitionReader]-[INFO] - Loading XML bean definitions from ServletContext resource [/WEB-INF/applicationContext.xml]2015-05-10 09:54:34 [org.springframework.beans.factory.xml.DefaultDocumentLoader]-[DEBUG] - Using JAXP provider [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl]2015-05-10 09:54:34 [org.springframework.beans.factory.xml.PluggableSchemaResolver]-[TRACE] - Trying to resolve XML entity with public id [null] and system id [http://www.springframework.org/schema/beans/spring-beans-3.0.xsd]2015-05-10 09:54:34 [org.springframework.beans.factory.xml.PluggableSchemaResolver]-[DEBUG] - Loading schema mappings from [META-INF/spring.schemas]2015-05-10 09:54:34 [org.springframework.beans.factory.xml.PluggableSchemaResolver]-[DEBUG] - Loaded schema mappings: {http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd=org/springframework/oxm/config/spring-oxm-3.0.xsd, http://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd, http://www.springframework.org/schema/jms/spring-jms-3.0.xsd=org/springframework/jms/config/spring-jms-3.0.xsd, http://www.springframework.org/schema/task/spring-task.xsd=org/springframework/scheduling/config/spring-task-3.0.xsd, http://www.springframework.org/schema/aop/spring-aop-3.0.xsd=org/springframework/aop/config/spring-aop-3.0.xsd, http://www.springframework.org/schema/aop/spring-aop-2.0.xsd=org/springframework/aop/config/spring-aop-2.0.xsd, http://www.springframework.org/schema/oxm/spring-oxm.xsd=org/springframework/oxm/config/spring-oxm-3.0.xsd, http://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd, http://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd, http://www.springframework.org/schema/jee/spring-jee-2.5.xsd=org/springframework/ejb/config/spring-jee-2.5.xsd, http://www.springframework.org/schema/aop/spring-aop.xsd=org/springframework/aop/config/spring-aop-3.0.xsd, http://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd, http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd=org/springframework/web/servlet/config/spring-mvc-3.0.xsd, http://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd, http://www.springframework.org/schema/task/spring-task-3.0.xsd=org/springframework/scheduling/config/spring-task-3.0.xsd, http://www.springframework.org/schema/tx/spring-tx-2.5.xsd=org/springframework/transaction/config/spring-tx-2.5.xsd, http://www.springframework.org/schema/context/spring-context-2.5.xsd=org/springframework/context/config/spring-context-2.5.xsd, http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd=org/springframework/jdbc/config/spring-jdbc-3.0.xsd, http://www.springframework.org/schema/tool/spring-tool-3.0.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd, http://www.springframework.org/schema/tx/spring-tx.xsd=org/springframework/transaction/config/spring-tx-3.0.xsd, http://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd, http://www.springframework.org/schema/util/spring-util-2.5.xsd=org/springframework/beans/factory/xml/spring-util-2.5.xsd, http://www.springframework.org/schema/lang/spring-lang.xsd=org/springframework/scripting/config/spring-lang-3.0.xsd, http://www.springframework.org/schema/lang/spring-lang-2.5.xsd=org/springframework/scripting/config/spring-lang-2.5.xsd, http://www.springframework.org/schema/jee/spring-jee-3.0.xsd=org/springframework/ejb/config/spring-jee-3.0.xsd, http://www.springframework.org/schema/jee/spring-jee-2.0.xsd=org/springframework/ejb/config/spring-jee-2.0.xsd, http://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context-3.0.xsd, http://www.springframework.org/schema/jee/spring-jee.xsd=org/springframework/ejb/config/spring-jee-3.0.xsd, http://www.springframework.org/schema/jms/spring-jms-2.5.xsd=org/springframework/jms/config/spring-jms-2.5.xsd, http://www.springframework.org/schema/jms/spring-jms.xsd=org/springframework/jms/config/spring-jms-3.0.xsd, http://www.springframework.org/schema/aop/spring-aop-2.5.xsd=org/springframework/aop/config/spring-aop-2.5.xsd, http://www.springframework.org/schema/mvc/spring-mvc.xsd=org/springframework/web/servlet/config/spring-mvc-3.0.xsd, http://www.springframework.org/schema/jdbc/spring-jdbc.xsd=org/springframework/jdbc/config/spring-jdbc-3.0.xsd, http://www.springframework.org/schema/tx/spring-tx-2.0.xsd=org/springframework/transaction/config/spring-tx-2.0.xsd, http://www.springframework.org/schema/tx/spring-tx-3.0.xsd=org/springframework/transaction/config/spring-tx-3.0.xsd, http://www.springframework.org/schema/context/spring-context-3.0.xsd=org/springframework/context/config/spring-context-3.0.xsd, http://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd, http://www.springframework.org/schema/util/spring-util-3.0.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd, http://www.springframework.org/schema/lang/spring-lang-3.0.xsd=org/springframework/scripting/config/spring-lang-3.0.xsd, http://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd, http://www.springframework.org/schema/lang/spring-lang-2.0.xsd=org/springframework/scripting/config/spring-lang-2.0.xsd, http://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd}2015-05-10 09:54:34 [org.springframework.beans.factory.xml.PluggableSchemaResolver]-[DEBUG] - Found XML schema [http://www.springframework.org/schema/beans/spring-beans-3.0.xsd] in classpath: org/springframework/beans/factory/xml/spring-beans-3.0.xsd2015-05-10 09:54:34 [org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader]-[DEBUG] - Loading bean definitions2015-05-10 09:54:34 [org.springframework.beans.factory.xml.XmlBeanDefinitionReader]-[DEBUG] - Loaded 0 bean definitions from location pattern [/WEB-INF/applicationContext.xml]2015-05-10 09:54:34 [org.springframework.web.context.support.XmlWebApplicationContext]-[DEBUG] - Bean factory for Root WebApplicationContext: org.springframework.beans.factory.support.DefaultListableBeanFactory@5eedf162: defining beans []; root of factory hierarchy2015-05-10 09:54:34 [org.springframework.web.context.support.XmlWebApplicationContext]-[DEBUG] - Unable to locate MessageSource with name 'messageSource': using default [org.springframework.context.support.DelegatingMessageSource@314b0824]2015-05-10 09:54:34 [org.springframework.web.context.support.XmlWebApplicationContext]-[DEBUG] - Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [org.springframework.context.event.SimpleApplicationEventMulticaster@708a538f]2015-05-10 09:54:34 [org.springframework.ui.context.support.UiApplicationContextUtils]-[DEBUG] - Unable to locate ThemeSource with name 'themeSource': using default [org.springframework.ui.context.support.ResourceBundleThemeSource@1fce66ba]2015-05-10 09:54:34 [org.springframework.beans.factory.support.DefaultListableBeanFactory]-[INFO] - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5eedf162: defining beans []; root of factory hierarchy2015-05-10 09:54:34 [org.springframework.web.context.support.XmlWebApplicationContext]-[DEBUG] - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@7cbc2c83]2015-05-10 09:54:34 [org.springframework.beans.factory.support.DefaultListableBeanFactory]-[DEBUG] - Returning cached instance of singleton bean 'lifecycleProcessor'2015-05-10 09:54:34 [org.springframework.web.context.support.XmlWebApplicationContext]-[TRACE] - Publishing event in Root WebApplicationContext: org.springframework.context.event.ContextRefreshedEvent[source=Root WebApplicationContext: startup date [Sun May 10 09:54:34 CST 2015]; root of context hierarchy]2015-05-10 09:54:34 [org.springframework.web.context.ContextLoader]-[DEBUG] - Published root WebApplicationContext as ServletContext attribute with name [org.springframework.web.context.WebApplicationContext.ROOT]2015-05-10 09:54:34 [org.springframework.web.context.ContextLoader]-[INFO] - Root WebApplicationContext: initialization completed in 230 ms2015-05-10 09:54:48 [org.apache.jsp.Log4j_jsp]-[FATAL] - 致命錯誤!2015-05-10 09:54:48 [org.apache.jsp.Log4j_jsp]-[ERROR] - 出錯資訊!2015-05-10 09:54:48 [org.apache.jsp.Log4j_jsp]-[INFO] - 普通訊息!2015-05-10 09:54:48 [org.apache.jsp.Log4j_jsp]-[DEBUG] - 調試資訊!
四、總結
Log4j一般不會像這樣直接寫在log4j.jsp中。一般處於那些try-catch異常結構中的catch裡面,或許一些操作檔案、資料庫的關鍵資料之間,直接給程式員看的。程式猿有空看看那個在log.txt,也就像保安有空看看閉路電視,來確定你的WEB工程到底正不正常。可以成為系統營運的一部分。