log4j

 Log4j建議只使用四個級別,優先級從高到低分別是ERROR、WARN、INFO、DEBUG。好比在這裏定義了INFO級別,只有等於及高於這個級別的才進行處理,css

   1、log4j使用步驟(重點在使用過程和初始化):
1.將log4j.jar相關包放到jsp-examples\WEB-INF\lib下;
2.在classpath下面創建log4j.properties;
3.完善log4j.properties內容:html

 
  1. log4j.rootLogger=warn, stdout,A1   
  2.   
  3. #配置輸出到控制檯   
  4. log4j.appender.stdout=org.apache.log4j.ConsoleAppender   
  5. log4j.appender.stdout.layout=org.apache.log4j.PatternLayout   
  6. log4j.appender.stdout.layout.ConversionPattern=(%F:%L) - %m%n   
  7.   
  8. log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender    
  9. log4j.appender.A1.layout=org.apache.log4j.HTMLLayout   
  10. log4j.appender.A1.File=${webappHome}/logs/${date}_log.html   
  11. log4j.appender.A1.MaxFileSize= 100KB  

   具體log4j.properties的配置方法參見http://hi.baidu.com/276668688/blog/item/e8d2fc1fdd8818c1a786698d.htmljava

4.初始化log4j的配置文件:有兩種方法
   方法一:
    a.新建一個初始化類,通常用Servlet或過濾器Log4JInit.javanode

 
  1. package log4j;    
  2. import java.io.*;    
  3. import javax.servlet.*;    
  4. import javax.servlet.http.*;    
  5. import org.apache.log4j.*;   
  6.   
  7. public class Log4JInit extends HttpServlet {   
  8.    public void init() throws ServletException{   
  9.        String prefix = getServletContext().getRealPath("/");    
  10.        String test = getServletContext().getRealPath("");    
  11.        System.out.println(prefix);    
  12.        System.out.println(test);    
  13.          
  14.        System.setProperty("webappHome", test);   
  15.        String file = getServletConfig().getInitParameter("log4j-config-file");    
  16.        System.out.println(prefix+file);    
  17.        // 從Servlet參數讀取log4j的配置文件    
  18.         if (file != null) {    
  19.          PropertyConfigurator.configure(prefix + file);    
  20.           
  21.        }   
  22.    }   
  23. }   

     注意:System.setProperty("webappHome", test);」這行代碼要出如今「PropertyConfigurator.configure(prefix + file);」這行代碼以前;由於這樣纔給"webappHome"設置值了,log4j.properties文件中的「log4j.appender.A1.file=${webappHome}/logs/tomcat_log_」中的「${webappHome}」這個環境變量才被賦值了,不然沒法輸出日誌文件;web

     b.配置web.xml文件spring

 
  1. <servlet>    
  2.    <servlet-name>log4jinit</servlet-name>    
  3.    <servlet-class>log4j.Log4JInit</servlet-class>    
  4.    <init-param>    
  5.        <param-name> log4j-config-file </param-name>    
  6.        <param-value>properties\log4j.properties</param-value>    
  7.    </init-param>    
  8.    <load-on-startup>1</load-on-startup>    
  9. </servlet>  

     注意:上面的load-on-startup應設爲1,以便在Web容器啓動時即裝入該Servlet。log4j.properties文件放在根的properties子目錄中,也能夠把它放在其它目錄中。應該把.properties文件集中存放,這樣方便管理。

   方法2、使用Spring已經寫好的過濾器
      a.配置web.xmlapache

 
  1. <context-param>  
  2.    <param-name>log4jConfigLocation</param-name>  
  3.    <param-value>/WEB-INF/config/log4j.properties</param-value>  
  4.  </context-param>     
  5.  <context-param>  
  6.    <param-name>log4jRefreshInterval</param-name>  
  7.    <param-value>6000</param-value>  
  8.  </context-param>  
  9.  <listener>  
  10.      <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>  
  11.  </listener>  

5.在webapp中使用log4j
   主要創建一個屬性private static Logger logger = Logger.getLogger(Log4jTest.class);tomcat

public class Hello extends HttpServlet {
      private static Logger logger = Logger.getLogger(Hello.class);多線程

      @Override
      protected void service(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
          System.out.println("Hello world!!");
          logger.debug("log4j加載成功!");
      }app

}

6.在具體使用的時候若是觸發了異常,就在生成以日期命名的html日誌文件tomcat_log_2007-03-05.html了!
  這個日誌的格式能夠在log4j.properties裏面配置.......

====================================================================================================================================================================================================
經常使用log4j配置

經常使用log4j配置,通常能夠採用兩種方式,.properties和.xml,下面舉兩個簡單的例子:

1、 log4j.properties

### 設置org.zblog域對應的級別INFO,DEBUG,WARN,ERROR和輸出地A1,A2 ##
log4j.category.org.zblog=ERROR,A1 
log4j.category.org.zblog=INFO,A2 
log4j.appender.A1=org.apache.log4j.ConsoleAppender 
### 設置輸出地A1,爲ConsoleAppender(控制檯) ##
log4j.appender.A1.layout=org.apache.log4j.PatternLayout 
### 設置A1的輸出佈局格式PatterLayout,(能夠靈活地指定佈局模式)##
log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n 
### 配置日誌輸出的格式##
log4j.appender.A2=org.apache.log4j.RollingFileAppender 
### 設置輸出地A2到文件(文件大小到達指定尺寸的時候產生一個新的文件)##
log4j.appender.A2.File=E:/study/log4j/zhuwei.html 
### 文件位置##
log4j.appender.A2.MaxFileSize=500KB 
### 文件大小##
log4j.appender.A2.MaxBackupIndex=1 
log4j.appender.A2.layout=org.apache.log4j.HTMLLayout 
##指定採用html方式輸出

2、 log4j.xml

<?xml version="1.0" encoding="GB2312" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="org.zblog.all" class="org.apache.log4j.RollingFileAppender">
<!-- 設置通道ID:org.zblog.all和輸出方式:org.apache.log4j.RollingFileAppender -->
   <param name="File" value="E:/study/log4j/all.output.log" /><!-- 設置File參數:日誌輸出文件名 -->
   <param name="Append" value="false" /><!-- 設置是否在從新啓動服務時,在原有日誌的基礎添加新日誌 -->
   <param name="MaxBackupIndex" value="10" /> 
   <layout class="org.apache.log4j.PatternLayout">
       <param name="ConversionPattern" value="%p (%c:%L)- %m%n" /><!-- 設置輸出文件項目和格式 -->
   </layout>
</appender>
<appender name="org.zblog.zcw" class="org.apache.log4j.RollingFileAppender">
   <param name="File" value="E:/study/log4j/zhuwei.output.log" />
   <param name="Append" value="true" />
   <param name="MaxFileSize" value="10240" /> <!-- 設置文件大小 -->
   <param name="MaxBackupIndex" value="10" /> 
   <layout class="org.apache.log4j.PatternLayout">
       <param name="ConversionPattern" value="%p (%c:%L)- %m%n" />
   </layout>
</appender>
<logger name="zcw.log"> <!-- 設置域名限制,即zcw.log域及如下的日誌均輸出到下面對應的通道中 -->
   <level value="debug" /><!-- 設置級別 -->
   <appender-ref ref="org.zblog.zcw" /><!-- 與前面的通道id相對應 -->
</logger>
<root> <!-- 設置接收全部輸出的通道 -->
   <appender-ref ref="org.zblog.all" /><!-- 與前面的通道id相對應 -->
</root>
</log4j:configuration>

3、 配置文件加載方法:

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.DOMConfigurator;
public class Log4jApp {
   public static void main(String[] args) {
       DOMConfigurator.configure("E:/study/log4j/log4j.xml");//加載.xml文件
       //PropertyConfigurator.configure("E:/study/log4j/log4j.properties");//加載.properties文件
       Logger log=Logger.getLogger("org.zblog.test");
       log.info("測試");
   }
}

4、 項目使用log4j

在web 應用中,能夠將配置文件的加載放在一個單獨的servlet中,並在web.xml中配置該servlet在應用啓動時候加載。對於在多人項目中,能夠給每個人設置一個輸出通道,這樣在每一個人在構建Logger時,用本身的域名稱,讓調試信息輸出到本身的log文件中。

5、 經常使用輸出格式

# -X號:X信息輸出時左對齊;
# %p:日誌信息級別
# %d{}:日誌信息產生時間
# %c:日誌信息所在地(類名)
# %m:產生的日誌具體信息
# %n:輸出日誌信息換行

===============================================================================================

log4j屬性含義

1)%r輸出程序開始執行以後的微秒數
2)%t輸出當前線程的名稱
3)%-5p輸出消息的層次。
4)%c 輸出category的名稱
5)-%m及s是日誌消息自己,%n是換行符。
  當前在模式字符串中你能夠嵌入任何想要輸出的字符。
  模式字符串中的模式以下:
%m:消息自己
%p:消息的層次
%r:從程序開始執行到當前日誌產生時的時間間隔(微秒)
%c:輸出當前日誌動做所在的category名稱。例如:若是category名稱是"a.b.c","%c{2}"將會輸出"b.c". {2}意謂着輸出「以點分隔開的category名稱的後兩個組件」,若是 {n}沒有,將會輸出整個category名稱.
%t:輸出當前線程的名稱
%x:輸出和當前線程相關聯的NDC(具體解釋見下文),尤爲用到像java servlets這樣的多客戶多線程的應用中。
%n:輸出平臺相關的換行符。
%%:輸出一個"%"字符
%d:輸出日誌產生時候的日期,固然能夠對日期的格式進行定製。例如:%d{HH:mm:ss,SSSS}或者是%d{dd MMM yyyy HH:mm:ss,SSSS},若是沒有指定後面的格式,將會輸出ISO8601的格式。
%l:輸出位置信息,至關於%C.%M(%F:%L)的組合。
%C:輸出日誌消息產生時所在的類名,若是類名是「test.page.Class1」%C{1}表示輸出類名"Class1",%C{2}輸出"page.Class1",而%C則輸出"test.page.Class1"。
%M:輸出日誌消息產生時的方法名稱
%F:輸出日誌消息產生時所在的文件名稱
%L:輸出代碼中的行號
   能夠在%與模式字符之間加上修飾符來控制其最小寬度、最大寬度、和文本的對齊方式。如:
   1)%20c:指定輸出category的名稱,最小的寬度是20,若是category的名稱小於20的話,默認的狀況下右對齊。
  2) %-20c:指定輸出category的名稱,最小的寬度是20,若是category的名稱小於20的話,"-"號指定左對齊。
  3) %.30c:指定輸出category的名稱,最大的寬度是30,若是category的名稱大於30的話,就會將左邊多出的字符截掉,但小於30的話也不會有空格。
  4)%20.30c:若是category的名稱小於20就補空格,而且右對齊,若是其名稱長於30字符,就從左邊交遠銷出的字符截掉。
  4)%20.30c:
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
利用spring aop對日誌進行管理,仍是採用對比的方式進行,

修改前:

偶們的作法是在action裏記錄日誌,注意這個日誌是面向用戶的日誌,姑且稱它爲業務日誌,至於後臺日誌,則在此文章中暫不考慮,基本是經過log4j打印到後臺日誌文件中。看下面一段代碼: 


 

   1.  try  {   
   2.     employeInfoManageService.saveEmploye(vo, authForm.getLoginName());   
   3.   
   4.     LogVO logVO = new LogVO(Constants.LOG_LEVEL_INFO,   
   5.                 Constants.LOG_TYPE_BACK, "用戶:" + authForm.getLoginName()   
   6.                             + "增長員工成功!");   
   7.     logService.saveLog(logVO);   
   8. } catch (Exception e) {   
   9.     log.error(e);   
  10.     LogVO logVO = new LogVO(Constants.LOG_LEVEL_ERROR,   
  11.             Constants.LOG_TYPE_BACK, "用戶:" + authForm.getLoginName()   
  12.                             + "增長員工失敗!");   
  13.     try {   
  14.         logService.saveLog(logVO);   
  15.     } catch (Exception e1) {   
  16.         log.error(e1);     
  17.     return messageForward("error", "alert.db.exception",      
  18.                     new Object[] {});   }   
  19. }  

 

這段代碼實際上已經將寫日誌的過程封裝起來,開發者只須要傳入3個參數:操做者、是前臺系統仍是後臺系統、以及日誌的錯誤等級,其它的如操做者機器IP, 日誌時間等信息由系通通一設定,即便是這樣,若是一個action裏面有多個操做,代碼看起來也很是臃腫,並且給開發者增長了工做量,既然有了aop,爲 什麼不利用一下?看下面改造的代碼:

 

   1.  LogVO logVO = new LogVO(Constants.LOG_LEVEL_INFO,   
   2.                 Constants.LOG_TYPE_BACK, "用戶:" + authForm.getLoginName()   
   3.                             + "增長員工");   
   4. try  {   
   5.     employeInfoManageService.saveEmploye(vo, authForm.getLoginName(), logVO);   
   6. } catch (Exception e) {   
   7.     log.error(e);   
   8.     return messageForward("error", "alert.db.exception",   
   9.                     new Object[] {});   
  10. }  
既然是應用到aop,固然少不了aop的配置了,看下面的配置代碼:

 

 

   1.  <aop:config>  
   2.     <aop:advisor pointcut="execution(* *..*Service.*(..))" advice-ref="txAdvice"/>  
     3.     <aop:advisor pointcut="execution(* *..*Service.save*(..)) || execution(* *..*Service.update*(..)) || execution(* *..*Service.delete*(..))" advice-ref="logAfterAdvice"/>  
   4. </aop:config>  
   5.   
   6. <bean id="logAfterAdvice" class="com.fudannet.framework.aop.LogAfterAdvice"/>  
噢,aop:config的第一行是否是很熟悉啊,對,就是咱們前面所配置的事務管理,這裏,應該很清楚採用統一的aop配置的好處了吧。下面貼出logAfterAdvice的代碼:

 

 

   1.  public void afterReturning(Object returnObj, Method method, Object[] args,   
   2.             Object targetObj) throws Throwable  {   
   3.     if(method.getName().equals("saveLog")) return;   
   4.     for(int i = 0; i < args.length; i++){   
   5.         if(args[i] instanceof LogVO){   
   6.             log.info("開始寫入日誌......");   
   7.             writeLog((LogVO)args[i]);   
   8.         }   
   9.     }   
  10. }   
  11.   
  12. private void writeLog(LogVO vo){   
  13.     try {   
  14.         vo.setDescription(vo.getDescription() + "成功!");   
  15.         logService.saveLog(vo);   
  16.     } catch (RuntimeException e) {   
  17.         log.error(e);   
  18. }   
  19.   
  20. public void setLogService(LogService logService) {   
  21.     this.logService = logService;   
  22. }  

 

這段代碼應該很清楚了,將logService注入到攔截log的advice裏,進行正確操做的日誌記錄,而afterReturning方法裏 的第一行判斷是因爲logService裏的寫日誌的方法是以save開始的。因此,若是攔截器攔截到此方法,不須要記錄日誌。

正確的日誌記錄完,固然若是發生異常,咱們須要記錄操做的失敗日誌,固然了,咱們也是經過aop來作,可是此次是經過實現exception advice來實現,代碼以下: 

   1.  public void afterThrowing(Method method,Object[] args,Object target,Exception e) throws Throwable  {   
   2.     if(method.getName().equals("saveLog")) return;   
   3.     for(int i = 0; i < args.length; i++){   
   4.         if(args[i] instanceof LogVO){   
   5.             log.info開始寫入日誌......");  
   6.             writeLog((LogVO)args[i]);  
   7.         }  
   8.     }  
   9. }  
  10.  
  11. private void writeLog(LogVO vo){  
  12.     try {  
  13.         vo.setDescription(vo.getDescription() + "失敗!");   
  14.         logThrowService.saveLog(vo);   
  15.     } catch (RuntimeException e) {   
  16.         log.error(e);   
  17.     }   
  18. }   
  19.   
  20. public void setLogThrowService(LogService logThrowService) {   
  21.     this.logThrowService = logThrowService;   
  22. }  

 

上面代碼已經很好的說明了,若是發生exception的話,日誌是怎麼記錄的,這裏要提到的一點的是,異常的處理稍微有一些複雜,就拿本例的代碼能看出 來,只要在service層有異常的時候,都會記錄失敗日誌,實際上,不少時候,未必是這樣,在某個模塊,可能須要定義一種特殊的異常,而一旦這種異常發 生,則須要進入另一個流程或者作一些特殊的處理,這個時候須要根據具體狀況作一些變動,好比在上面代碼咱們加上:
   1.  public void afterThrowing(Method method,Object[] args,Object target,OrderException e) throws Throwable  {   
   2.     log.info("......");   
   3.     //do something   
   4. }  
則若是OrderException被拋出,就會到此方法中執行,而不會去寫日誌。
--------------------------------------------------------------------------------
其中的封裝方式雖然通常,可是仍是比較好的解決了問題!對於LogVO類咱們能夠把他繼續擴展下去,好比設定訪問用戶,IP,seq文等.

Spring AOP與log4j作簡單的異常日誌處理

1.在網上看了很多例子,下面本身實踐了一下。因爲系統開發的時候忘記了對異常的日誌處理,因此如今考慮加上,通過考慮決定使用spring的aop與log4j來作,這樣作的好處就是我不用在每一個類裏面try{}catch或者拋出異常。由於類已經寫了好多好多了。要是一個一個弄工做量是很大的 。 
下面說下簡單的實現過程,首先啊,在項目工程中的src目錄中加入log4j.properties,內容以下: 

###設置日誌級別### 
###這部分是將info信息輸出到控制檯### 
log4j.rootLogger = info,stdout,F 
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{ABSOLUTE} %5p %c{1}:%L - %m%n 

###錯誤日誌配置### 
log4j.appender.F = org.apache.log4j.DailyRollingFileAppender 
##輸出格式爲自定義的HTML## 
log4j.appender.F.layout = com.yale.sys.log.FormatHTMLLayout 
log4j.appender.F.Threshold = ERROR 
log4j.appender.F.Append=true 
##錯誤文件存放位置## 
log4j.appender.F.File=error.html 
##天天滾動一次文件,即天天產生一個新的文件,文件名字eg:error.html.2012-06-18.html## 
log4j.appender.F.DatePattern='.'yyyy-MM-dd'.html' 

-------------------------------耐心的看下去 ----------------------------------- 
其次呢,看上面紅色那部分,由於是要將輸出日誌信息存儲到html文件中,因此重寫了下log4j中HTMLLayout類,代碼片斷: 

Java代碼   收藏代碼
  1. package com.yale.sys.log;  
  2.   
  3. import java.text.SimpleDateFormat;  
  4. import org.apache.log4j.HTMLLayout;  
  5. import org.apache.log4j.Layout;  
  6. import org.apache.log4j.Level;  
  7. import org.apache.log4j.helpers.Transform;  
  8. import org.apache.log4j.spi.LocationInfo;  
  9. import org.apache.log4j.spi.LoggingEvent;  
  10. /** 
  11.  * log4j輸出到html格式重寫 
  12.  * @author yale 
  13.  * 
  14.  */  
  15. public class FormatHTMLLayout extends HTMLLayout {     
  16.         
  17.     public FormatHTMLLayout() {     
  18.     }     
  19. [/size]    
  20.     protected final int BUF_SIZE = 256;     
  21.     
  22.     protected final int MAX_CAPACITY = 1024;     
  23.     
  24.     static String TRACE_PREFIX = "<br>&nbsp;&nbsp;&nbsp;&nbsp;";     
  25.     
  26.     // output buffer appended to when format() is invoked     
  27.     private StringBuffer sbuf = new StringBuffer(BUF_SIZE);     
  28.          
  29.     String title="系統錯誤日誌";     
  30.     
  31.     /**   
  32.      * A string constant used in naming the option for setting the the HTML   
  33.      * document title. Current value of this string constant is <b>Title</b>.   
  34.      */    
  35.     public static final String TITLE_OPTION = "Title";     
  36.     
  37.     // Print no location info by default     
  38.     boolean locationInfo = true;     
  39.          
  40.     public String format(LoggingEvent event) {     
  41.         if (sbuf.capacity() > MAX_CAPACITY) {     
  42.             sbuf = new StringBuffer(BUF_SIZE);     
  43.         } else {     
  44.             sbuf.setLength(0);     
  45.         }     
  46.         sbuf.append(Layout.LINE_SEP + "<tr>" + Layout.LINE_SEP);     
  47.              
  48.      
  49.         sbuf.append("<td>");     
  50.         sbuf.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date()));     
  51.         sbuf.append("</td>" + Layout.LINE_SEP);     
  52.     
  53.    
  54.         sbuf.append("<td title=\"級別\">");     
  55.         if (event.getLevel().equals(Level.FATAL)) {     
  56.             sbuf.append("<font color=\"#339933\">");     
  57.             sbuf.append(Transform.escapeTags(String.valueOf(event.getLevel())));     
  58.             sbuf.append("</font>");     
  59.         } else if (event.getLevel().isGreaterOrEqual(Level.WARN)) {     
  60.             sbuf.append("<font color=\"#993300\"><strong>");     
  61.             sbuf.append(Transform.escapeTags(String.valueOf(event.getLevel())));     
  62.             sbuf.append("</strong></font>");     
  63.         } else {     
  64.             sbuf.append("<font color=\"green\">");     
  65.             sbuf.append(Transform.escapeTags(String.valueOf(event.getLevel())));     
  66.             sbuf.append("</font>");     
  67.         }     
  68.         sbuf.append("</td>" + Layout.LINE_SEP);     
  69.              
  70.   
  71.         if (locationInfo) {     
  72.             LocationInfo locInfo = event.getLocationInformation();     
  73.             sbuf.append("<td title=\"錯誤\">");   
  74.             sbuf.append("<font color=\"red\">");   
  75.             sbuf.append(Transform.escapeTags(locInfo.getFileName()));    
  76.             sbuf.append(':');    
  77.             sbuf.append(locInfo.getMethodName()).append("()方法中第");  
  78.             sbuf.append(locInfo.getLineNumber()).append("行出現錯誤");   
  79.             sbuf.append("</font>");   
  80.             sbuf.append("</td>" + Layout.LINE_SEP);    
  81.         }    
  82.             
  83.             
  84.   
  85.             
  86.         sbuf.append("<td title=\"錯誤信息\">");     
  87.         sbuf.append(Transform.escapeTags(event.getRenderedMessage()));     
  88.         sbuf.append("</td>" + Layout.LINE_SEP);     
  89.         sbuf.append("</tr>" + Layout.LINE_SEP);     
  90.     
  91.         if (event.getNDC() != null) {     
  92.             sbuf.append("<tr><td bgcolor=\"#EEEEEE\" style=\"font-size : xx-small;\" colspan=\"6\" title=\"Nested Diagnostic Context\">");     
  93.             sbuf.append("NDC: " + Transform.escapeTags(event.getNDC()));     
  94.             sbuf.append("</td></tr>" + Layout.LINE_SEP);     
  95.         }     
  96.     
  97.         String[] s = event.getThrowableStrRep();     
  98.         if (s != null) {     
  99.             sbuf.append("<tr><td bgcolor=\"#993300\" style=\"color:White; font-size : xx-small;\" colspan=\"4\">");     
  100.             appendThrowableAsHTML(s, sbuf);     
  101.             sbuf.append("</td></tr>" + Layout.LINE_SEP);     
  102.         }     
  103.         return sbuf.toString();     
  104.     }     
  105.     
  106.     private void appendThrowableAsHTML(String[] s, StringBuffer sbuf) {     
  107.         if (s != null) {     
  108.             int len = s.length;     
  109.             if (len == 0)     
  110.                 return;     
  111.             sbuf.append(Transform.escapeTags(s[0]));     
  112.             sbuf.append(Layout.LINE_SEP);     
  113.             for (int i = 1; i < len; i++) {     
  114.                 sbuf.append(TRACE_PREFIX);     
  115.                 sbuf.append(Transform.escapeTags(s[i]));     
  116.                 sbuf.append(Layout.LINE_SEP);     
  117.             }     
  118.         }     
  119.     }     
  120.     
  121.     /**   
  122.      * Returns appropriate HTML headers.   
  123.      */    
  124.     public String getHeader() {     
  125.         sbuf.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">" + Layout.LINE_SEP);     
  126.         sbuf.append("<html>" + Layout.LINE_SEP);     
  127.         sbuf.append("<head>" + Layout.LINE_SEP);     
  128.         sbuf.append("<title>" + title + "</title>" + Layout.LINE_SEP);     
  129.         sbuf.append("<style type=\"text/css\">" + Layout.LINE_SEP);     
  130.         sbuf.append("<!--" + Layout.LINE_SEP);     
  131.         sbuf.append("body, table {font-family: '宋體',arial,sans-serif; font-size: 12px;}" + Layout.LINE_SEP);     
  132.         sbuf.append("th {background: #336699; color: #FFFFFF; text-align: left;}" + Layout.LINE_SEP);     
  133.         sbuf.append("-->" + Layout.LINE_SEP);     
  134.         sbuf.append("</style>" + Layout.LINE_SEP);     
  135.         sbuf.append("</head>" + Layout.LINE_SEP);     
  136.         sbuf.append("<body bgcolor=\"#FFFFFF\" topmargin=\"6\" leftmargin=\"6\">" + Layout.LINE_SEP);     
  137.         sbuf.append("<table cellspacing=\"0\" cellpadding=\"4\" border=\"1\" bordercolor=\"#224466\" width=\"100%\">" + Layout.LINE_SEP);     
  138.         sbuf.append("<tr>" + Layout.LINE_SEP);     
  139.         sbuf.append("<th>執行時間</th>" + Layout.LINE_SEP);     
  140.         sbuf.append("<th>級別</th>" + Layout.LINE_SEP);     
  141.         if (locationInfo) {     
  142.             sbuf.append("<th>所在行</th>" + Layout.LINE_SEP);     
  143.         }     
  144.         sbuf.append("<th>錯誤信息</th>" + Layout.LINE_SEP);     
  145.         sbuf.append("</tr>" + Layout.LINE_SEP);     
  146.         sbuf.append("<br></br>" + Layout.LINE_SEP);     
  147.         return sbuf.toString();     
  148.     }     
  149.     
  150. }   


----------------------------耐心點往下看,就要沒了 -------------------------------------------------- 
再來就是錯誤文件error.html的存儲位置,想要放在項目的WebRoot下,因而就寫了個servlet,代碼片斷: 

Java代碼   收藏代碼
  1. package com.yale.sys.log;  
  2. import java.io.FileNotFoundException;  
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.util.Properties;  
  6.   
  7. import javax.servlet.Servlet;  
  8. import javax.servlet.ServletConfig;  
  9. import javax.servlet.ServletException;  
  10. import javax.servlet.http.HttpServlet;  
  11.   
  12.   
  13. import org.apache.log4j.PropertyConfigurator;  
  14.   
  15. /** 
  16.  * 初始化日誌錯誤文件存放的路徑 
  17.  */  
  18. public class LogFileSavePathServlet extends HttpServlet {  
  19.     private static final long serialVersionUID = 1L;  
  20.          
  21.     /** 
  22.      * @see HttpServlet#HttpServlet() 
  23.      */  
  24.     public LogFileSavePathServlet() {  
  25.         super();  
  26.         // TODO Auto-generated constructor stub  
  27.     }  
  28.   
  29.     /** 
  30.      * @see Servlet#init(ServletConfig) 
  31.      */  
  32.     public void init() throws ServletException {  
  33.         //得到系統的路徑 /WebRoot  
  34.       
  35.         String rootPath = this.getServletContext().getRealPath("/");  
  36.         //得到log4j.properties的輸入流  
  37.         InputStream is =this.getClass().getClassLoader().getResourceAsStream("log4j.properties");  
  38.         Properties prop = new Properties();       
  39.         try {  
  40.             prop.load(is);  
  41.         } catch (FileNotFoundException e) {  
  42.             e.printStackTrace();  
  43.         } catch (IOException e) {  
  44.             e.printStackTrace();  
  45.         }   
  46.          //設置日誌文件的輸出路徑     
  47.         prop.setProperty("log4j.appender.F.File",rootPath+prop.getProperty("log4j.appender.F.File"));  
  48.         prop.setProperty("log4j.appender.F.DatePattern",rootPath+prop.getProperty("log4j.appender.F.DatePattern"));  
  49.         //加載配置項     
  50.         PropertyConfigurator.configure(prop);   
  51.         super.init();  
  52.     }  
  53.   
  54.   
  55.   
  56. }  


注意啦,錯誤文件存儲的路徑不容許空格上面亂碼七糟的,必定要注意哦。 
寫完這個servlet,咱們不能忘記初始化,您說對不對啊,因此啊,web.xml就像下面這個樣子了: 

Java代碼   收藏代碼
  1. <!DOCTYPE web-app PUBLIC  
  2.  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"  
  3.  "http://java.sun.com/dtd/web-app_2_3.dtd" >  
  4. <web-app>  
  5. <!-- 日誌文件存儲路徑初始化-->  
  6.     <servlet>  
  7.         <servlet-name>LogFileSavePathServlet</servlet-name>  
  8.         <display-name>LogFileSavePathServlet</display-name>  
  9.         <description></description>  
  10.     <servlet-class>com.peoplespot.sys.log.LogFileSavePathServlet</servlet-class>  
  11.         <load-on-startup>0</load-on-startup>   
  12.     </servlet>  
  13.       <servlet-mapping>  
  14.         <servlet-name>LogFileSavePathServlet</servlet-name>  
  15.         <url-pattern>/LogFileSavePathServlet</url-pattern>  
  16.     </servlet-mapping>  
  17. </web-app>  


--------------------------------下面就開始和spring aop相關啦,看吧,看吧----------------------- 
再一次首先,寫一個系統異常日誌攔截器類,您看: 

Java代碼   收藏代碼
  1. package com.yale.sys.log;  
  2.   
  3. import org.apache.log4j.Logger;  
  4. import org.aspectj.lang.ProceedingJoinPoint;  
  5.   
  6. /** 
  7.  * 系統異常日誌攔截器 
  8.  * @author yale 
  9.  * 
  10.  */  
  11. public class LogInterceptor {  
  12.       
  13.      static Logger logger = Logger.getLogger(LogInterceptor.class);  
  14.      public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {    
  15.          StringBuffer sb = new StringBuffer();  
  16.         try{    
  17.             Object result = joinPoint.proceed();    
  18.             return result;    
  19.         }catch(Exception e){    
  20.             sb.append("開始方法:"+joinPoint.getTarget().getClass() + "." + joinPoint.getSignature().getName()+ "()  ");  
  21.             sb.append("錯誤信息以下:["+e.getMessage()+"]");  
  22.             logger.error(sb.toString());   
  23.         }  
  24.         return "error";//由於用到了strut2,因此出現異常會返回到<result name="error">/erreo.jsp</result>這個頁面中,固然啦,你也能夠配置成全局的異常返回頁。  
  25.     }    
  26. }  


上面這個類,主要用到了aspectj中的ProceedingJoinPoint,支持的是<aop:around />。 
類寫完了,可是spring配置文件applicationContext.xml尚未搞啊,因此搞一下: 

Java代碼   收藏代碼
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.     xsi:schemaLocation="   
  6.         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd   
  7.         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd   
  8.         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">  
  9.   
  10. <!-- 配置日誌攔截器 -->  
  11.     <bean id="logInterceptor" class="com.yale.sys.log.LogInterceptor"></bean>  
  12.       
  13.     <aop:config proxy-target-class="true">  
  14.         <aop:aspect id="logAspectSYS" ref="logInterceptor">  
  15.             <aop:around method="invoke" pointcut="execution(public * com.yale.live.action..*.*(..))" />  
  16.         </aop:aspect>  
  17.             <aop:aspect id="logAspectDNA" ref="logInterceptor">  
  18.             <aop:around method="invoke" pointcut="execution(public * com.yale.sys.action..*.*(..))" />  
  19.         </aop:aspect>  
  20.     </aop:config>  
  21. </beans>  


小插曲:看見<aop:config>節點中proxy-target-class="true"這個屬性了吧,當我不加的時候,啓動項目,訪問action代碼,就好比是LoginAction中的login()方法,不幸的是他報錯了,相似於 
java.lang.NoSuchMethodException: $Proxy54.login(),但是回去一看,有寫過這個login方法啊, $Proxy54又是怎麼回事呢?由於你加入aop功能了,但是spring是這麼幹的,默認啊實現的是接口注入,關聯的實現類。這裏實現注入類,因此出現了異常。要怎麼解決呢,因而就要加上proxy-target-class="true"屬性,接下來啓動項目吧,你會發現不幸的事情又發生了,又報錯了: 
org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces. 
提示的很明顯,少jar包了,因此就加吧,可是加jar的時候也要注意了: 
須要導入的jar包是cglib-nodep-2.1_3.jar(這裏面整合了asm)或者(asm-2.2.3.jar和cglib-2.2.jar 。)由於cglib須要asm的支持。 
到此完成。 
啓動項目開始運行吧,模擬了下一個異常,輸出到html最終這樣啦: 

相關文章
相關標籤/搜索