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