|
本文來自 http://www./topic/71996
本人感覺還是很有借鑒意義,所以在此貼出,加以評論! 原文如下: --------------------------------------------------------------------- 利用spring aop對日志進行管理,還是采用對比的方式進行, 修改前: 偶們的做法是在action里記錄日志,注意這個日志是面向用戶的日志,姑且稱它為業(yè)務(wù)日志,至于后臺日志,則在此文章中暫不考慮,基本是通過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. } ![]()
這段代碼實際上已經(jīng)將寫日志的過程封裝起來,開發(fā)者只需要傳入3個參數(shù):操作者、是前臺系統(tǒng)還是后臺系統(tǒng)、以及日志的錯誤等級,其它的如操作者機器IP, 日志時間等信息由系統(tǒng)統(tǒng)一設(shè)定,即使是這樣,如果一個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. } ![]()
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"/> ![]()
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. } ![]()
這段代碼應(yīng)該很清楚了,將logService注入到攔截log的advice里,進行正確操作的日志記錄,而afterReturning方法里 的第一行判斷是由于logService里的寫日志的方法是以save開始的。所以,如果攔截器攔截到此方法,不需要記錄日志。 正確的日志記錄完,當(dāng)然如果發(fā)生異常,我們需要記錄操作的失敗日志,當(dāng)然了,我們也是通過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的話,日志是怎么記錄的,這里要提到的一點的是,異常的處理稍微有一些復(fù)雜,就拿本例的代碼能看出 來,只要在service層有異常的時候,都會記錄失敗日志,實際上,很多時候,未必是這樣,在某個模塊,可能需要定義一種特殊的異常,而一旦這種異常發(fā) 生,則需要進入另外一個流程或者做一些特殊的處理,這個時候需要根據(jù)具體情況做一些變更,比如在上面代碼我們加上: 1. public void afterThrowing(Method method,Object[] args,Object target,OrderException e) throws Throwable ...{ 2. log.info("......"); 3. //do something 4. } ![]() -------------------------------------------------------------------------------- 其中的封裝方式雖然一般,但是還是比較好的解決了問題!對于LogVO類我們可以把他繼續(xù)擴展下去,比如設(shè)定訪問用戶,IP,seq文等. Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1621513 |
|
|