本文來自 http://www./topic/71996 本人感覺還是很有借鑒意義,所以在此貼出,加以評論! 原文如下: --------------------------------------------------------------------- 利用spring aop對日志進行管理,還是采用對比的方式進行,
修改前:
偶們的做法是在action里記錄日志,注意這個日志是面向用戶的日志,姑且稱它為業(yè)務日志,至于后臺日志,則在此文章中暫不考慮,基本是通過log4j打印到后臺日志文件中??聪旅嬉欢未a:
 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. }

這段代碼實際上已經(jīng)將寫日志的過程封裝起來,開發(fā)者只需要傳入3個參數(shù):操作者、是前臺系統(tǒng)還是后臺系統(tǒng)、以及日志的錯誤等級,其它的如操作者機器IP, 日志時間等信息由系統(tǒng)統(tǒng)一設定,即使是這樣,如果一個action里面有多個操作,代碼看起來也非常臃腫,而且給開發(fā)者增加了工作量,既然有了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的第一行是不是很熟悉啊,對,就是我們前面所配置的事務管理,這里,應該很清楚采用統(tǒng)一的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開始的。所以,如果攔截器攔截到此方法,不需要記錄日志。
正確的日志記錄完,當然如果發(fā)生異常,我們需要記錄操作的失敗日志,當然了,我們也是通過aop來做,但是這次是通過實現(xiàn)exception advice來實現(xiàn),代碼如下:
 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. }

上面代碼已經(jīng)很好的說明了,如果發(fā)生exception的話,日志是怎么記錄的,這里要提到的一點的是,異常的處理稍微有一些復雜,就拿本例的代碼能看出 來,只要在service層有異常的時候,都會記錄失敗日志,實際上,很多時候,未必是這樣,在某個模塊,可能需要定義一種特殊的異常,而一旦這種異常發(fā) 生,則需要進入另外一個流程或者做一些特殊的處理,這個時候需要根據(jù)具體情況做一些變更,比如在上面代碼我們加上:
 1. public void afterThrowing(Method method,Object[] args,Object target,OrderException e) throws Throwable ...{
2. log.info("......");
3. //do something
4. }

則如果OrderException被拋出,就會到此方法中執(zhí)行,而不會去寫日志。 -------------------------------------------------------------------------------- 其中的封裝方式雖然一般,但是還是比較好的解決了問題!對于 LogVO類我們可以把他繼續(xù)擴展下去,比如設定訪問用戶,IP,seq文等.
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1621513
|