log4j在web工程中的應用


這是來某外包公司的第五個星期,時間過得真快啊,又到了周一,也意味着來這里打了4周的醬油啦。

公司沒人對我負責,基本上處於放羊的狀態,指派的任務無人講解,看起來遙遙無期,口袋空空(沒錢),更慘的是精神世界也空空(主要一天敲不到50行代碼,看着其他同學在其他公司BAT啦,網易啦,突飛猛進,感覺好虛),這么久啥都沒學到?

也不是吧,回憶一下上周老大給講的log4j,於是決定趁着沒忘干凈趕快整理一下,主要借助了其他博客的精華,回憶着老大的諄諄教誨,整理一下。

說正事之前先吐槽一下艹蛋的win10系統,強制自動更新,在8.10分拋給我一個10分鍾后自動重啟的通知,之后就趁我早晨腦袋蒙圈在10分鍾后強制重啟進行了更新,

自動重啟了N次,更新了一個半鍾頭,比重裝還慢...而且更新之后也沒發現哪里有不一樣的地方。事后琢磨如果不想更新可以這么做:把系統時間往前調整(逃軟件試用期也用過這一招),或者在控制面板中設置禁止自動更新。

在配置log4j的過程中回顧了一下以前的知識,提出了3個問題。

 

一.web基礎回顧

1.1什么是web工程

  

一個web工程,就是符合一套web標准(工程組織形式個人理解就是源代碼,中間代碼,各種文件怎么放),因為只有符合一個統一的標准,服務器才能更好的識別,運行。

左圖:下面沒有介紹的基本沒用到,所以也懶得理解了...

  是eclipse中一個名為web_log4j的web工程,src顧名思義就是源碼,下面存放着若干.java文件,我們面向對象編程就是在這里寫類,寫方法

  jreSystemLibrary是java運行依賴的類庫,自動生成

  webApplibrary下面是工程引用的外部jar包,一個引用過程是這樣的:將jar包文件拷貝到工程中,右擊buildpath,buildpath相當於將jar包里面的類引入,

  比如之前【beanUtile.封裝】這樣的代碼是沒有提示的,buildpath之后,該代碼出現了提示,按照提示import之后就可以使用beanUtil這個工具類,

  前后對比說明buildpath完成了jar包中的類導入到工程中的作用。引用外部類還可以采用直接引用的方式[add external jars],不利於代碼移植性,就不介紹啦。

  (舉個例子,你電腦上log4j.jar在c盤,換了一台電腦跑,程序還去c盤找這個文件,找不到就會報錯)

  這里要說清楚所謂引用類,就不得不說一下什么是jar包,jar包其實就是打包壓縮好的一堆.class文件,引用就是把外部的.class文件組合到工程里面的過程。如果想要查看jar包的源碼,

  還需要導入源碼。有趣的是自己也可以將一堆.class文件在cmd命令下打成jar包,自創jar包。

  在一個web工程中,依靠的是工程名:web_log4j提供對外訪問,對內web_log4j抽象成根目錄/(內部總使用相對路徑訪問),對於路徑問題有篇博客解釋的超級精辟:java獲取路徑問題,

  (一個常用做法是從當前類拿到完整路徑,或者是通過容器得到)

  獲得路徑可以通過IO流做輸入輸出,還有讀取配置文件也需要路徑,所以路徑很重要。

  這里插播一個有趣的問題,下面的代碼是錯誤的,錯在哪里?

  public static String s1=this.getClass().getClassLoader().getResource("/").getPath();

  或者說:java的static方法里面為什么不能用this關鍵字?

  這和jvm有關,jvm首先加載的是靜態部分,而this的含義是指當前對象,靜態部分加載進入的時候對象還沒有創建。

  這里再插播一個對比jdk,jre,jvm,

  我們利用JDK(調用JAVA API)開發了屬於我們自己的JAVA程序后,通過JDK中的編譯程序(javac)將我們的文本java文件編譯成JAVA字節碼,

  在JRE上運行這些JAVA字節碼,JVM解析這些字節碼,映射到CPU指令集或OS的系統調用

  回到web工程的主題:

右圖:build文件夾下存放着編譯好的.class文件,src放源碼,webcontent下面的web-info存放着jar包和配置文件

工程運行所依賴的配置文件(.properties文件:比如用於配置數據庫連接的用戶名,密碼;.xml文件,配置類,常數等關系的文件);.class文件(外部jar包,src編譯形成的.class文件)

至此全部介紹完畢,其中大部分位於web-inf目錄下,由此可見這是一個很重要的目錄。而web.xml關系到一個web工程全局的初始化設置,接下來就說一說我所見過的配置,看明白了web.xml文件,這個工程用到哪些技術,是怎樣一個結構基本上有了一個全局性的了解。

 

1.2一個web.xml文件的解讀

 

<?xml version="1.0" encoding="UTF-8"?>  
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns="http://java.sun.com/xml/ns/javaee"  
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
    id="WebApp_ID" version="3.0">  
    <display-name>LogLearning</display-name>  

    <servlet>  
        <servlet-name>Log4JTestServlet</servlet-name>  
        <servlet-class>com.mucfc.Log4JTestServlet</servlet-class>  
    </servlet>  

    <servlet-mapping>  
        <servlet-name>Log4JTestServlet</servlet-name>  
        <url-pattern>/test</url-pattern>  
    </servlet-mapping>   

        <!-- Spring 容器加載 -->  
    <listener>  
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
    </listener>  
    <context-param>  
        <param-name>contextConfigLocation</param-name>  
        <param-value>classpath:applicationContext.xml</param-value>  
    </context-param>   

    <!-- 設置根目錄 -->  
    <context-param>    
        <param-name>webAppRootKey</param-name>    
        <param-value>webapp.root</param-value>    
    </context-param>    

    <context-param>  
        <param-name>log4jConfigLocation</param-name>  
        <param-value>/WEB-INF/classes/log4j.properties</param-value>  
    </context-param>  
    <!-- 3000表示 開一條watchdog線程每60秒掃描一下配置文件的變化;這樣便於日志存放位置的改變 -->  
    <context-param>    
         <param-name>log4jRefreshInterval</param-name>    
         <param-value>3000</param-value>    
    </context-param>   
    <listener>  
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>  
    </listener>   

</web-app>

 

最前面是約束,這個web.xml中主要配置了servlet和listener

servlet包含兩個標簽<servlet>和<servlet-mapping>

其中servlet-name可以隨便起,但是倆標簽里的name一定要一致,之所以這樣做,是因為前一個servlet綁定了servlet類(拿到request,response處理並且返回的代碼,說簡單點,控制代碼就寫在<servlet-class>指定的類里面,而且指定了初始化參數),后一個url-mapping(假設配成/test)則是提供了訪問路徑:如localhost:8080/web_log4j/test,就是在訪問這個servlet呢,訪問路徑和后台代碼要綁定,靠的是共有的名字,所謂的servlet之所以能實現交互的原因就是這樣。既有訪問路徑,又有后台處理代碼,request和response是一堆郵差,扮演了信息載體的角色。

listener標簽則配置了監聽器,其中org類位於jar包中,這里所謂的監聽器到底是什么東西呢?

1.隨着web應用的啟動開始啟動,也就是說一開始就發揮了作用

2.不負責響應用戶的請求,也就是說只有一行<listener>類</listener>,無需配置url

第一個監聽器:ContextLoaderListener和

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:applicationContext.xml</param-value>

</context-param>

搭配使用,使得context載入配置文件applicationContext.xml(里面放置着配置好的bean),所謂classpath指代的是web-info/classes目錄,直接把spring的配置關系載入了

webapp.root可以用於獲取系統根目錄,具體代碼System.getRoot("...")

第二個監聽器:log4jConfigListener

<context-param>

<param-name>log4jConfigLocation</param-name>

<param-value>/WEB-INF/classes/log4j.properties</param-value>

</context-param>

搭配使用載入了log4j文件的位置。
對監聽器作用理解如下:
只有一行,配置指向jar包里面的某個類,和某些特定參數配合使用,為其指定初始化模式(比如顯示了配置文件位置)
這里也可以做一個逆向思考:計算機不是人,怎么讀取配置文件呢?web.xml首先是web默認的全局配置文件,里面配置了監聽器從應用啟動開始啟動
通過一些參數來找到配置文件。

 

二 log4j的使用

2.1log4j介紹

就是跟日志掛鈎的東西,大部分web應用部署在linux上,要想時時刻刻記錄運行狀態,就得依靠一種叫日志的東西,運行狀態,出錯,異常統統記錄在案,出問題了回頭也能查到,日志的實體就是.log后綴的文件。

Log4j由三個重要的組件構成:日志信息的優先級,日志信息的輸出目的地,日志信息的輸出格式。日志信息的優先級從高到低有ERROR、WARN、 INFO、DEBUG,分別用來指定這條日志信息的重要程度;日志信息的輸出目的地指定了日志將打印到控制台還是文件中;而輸出格式則控制了日志信息的顯 示內容。

2.2log4j.properties文件解讀

 

### 設置###
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

 

log4j.rootLogger = debug,stdout,D,E

定義”頂“為debug,意為debug以下的信息都可以輸出,appenderName1為stdout(用於控制台輸出),D(debug),E(error)
PatternLayout表示按照指定格式輸出,才有后面的規則
[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n:
除了特殊含義字符,其他字符按照原樣輸出
p:[debug]級別,d:日期樣式,l:輸出日志事件發生的位置,n:回車換行,m:指定的消息(這才是重點)

除了控制台,還指定了error.log和debug.log作為輸出文件
2.3log4j的代碼應用
static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName ()[一般是當前類,因為記載了當前類的debug信息] )
PropertyConfigurator.configure ( String configFilename) :讀取使用Java的特性文件編寫的配置文件。
[這一步也可以在spring中配置指定的路徑]
Logger.debug ( Object message ) ; :跟上面對應的m一樣,輸出debug信息
三遺留問題
3.1上面僅僅是做了一個實驗,相當於helloword,在實際應用中,log4j是如何記載產生的異常的?
  或者說,上面的message是自己寫的,如果一段代碼跑崩了,日志是怎樣記錄信息的?
3.2每天產生數以萬計的日志記錄,如何查看?里面有沒有什么技巧?



 

 




 

 

 

 

  

 

  

 

 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM