轉載請注明出處:http://www.cnblogs.com/Joanna-Yan/p/6567672.html
項目日志記錄是項目開發、運營必不可少的內容,有了它可以對系統有整體的把控,出現任何問題都有蹤跡可尋。
如果用純OOP思想進行日志處理,會發現每個邏輯部分總會混入日志處理的代碼,顯得純OOP思想的設計不倫不類。如果日志的類型需求有變動,則需要去每個邏輯單元中修改Java代碼。需求再變更的話這將是一個非常繁瑣的工作。因此,日志處理應該是項目中單獨的一部分,我們在進行系統開發時,不應該再來考慮日志處理。而AOP可以讓我們更加專注於項目的業務編碼,無需顧慮日志問題。
首先簡單介紹下AOP(Aspect Oriented Programming):
AOP是OOP的延續,是一種分散關注的編程方法,將“關注”封裝在切面中,實現了調用者與被調用者之間的解耦合。
分散關注:將通用需求功能從不相關的類中分離出來,同時能夠使得多個類共享一個行為,一旦行為發生改變,不必修改很多類,只需要修改這個行為就可以。
面向對象是縱向結構的,它能夠使系統的邏輯單元更加清晰。
面向切面是橫切結構的,它針對業務邏輯層的切面進行提取。比如切面完成一個功能,這一功能卻在每個模塊中都有涉及,他就像刀切豆腐一樣切進系統,能夠對系統完成同一控制。
疑慮:donet程序部署在服務器就能運行,而Java程序卻多一道工序,非得部署在容器里面才能運行呢?J2EE為什么要除非J2EE容器和J2EE應用系統呢?
答案:J2EE容器實際上是分離一般應用系統中通用的部分。像事務、安全、數據庫連接池等等這些功能,將這些分離出來做成一個通用的框架。這些功能機制的設計開發有一定的難度,同時運行的穩定性和快速性都非常重要,必須經過長時間調試和運行經驗積累而成,慢慢才形成了像Tomcat、JBoss、WebLogic等J2EE容器服務產品。簡單來說,J2EE中分出的容器,就是將大多數軟件中都會用到的東西拿了出來,時間長了慢慢的就成了產品。
從J2EE系統划分為容器和應用系統兩個方面,我們可以看到一種分散關注的思路。
實現過程:
1.涉及的jar包:
spring.jar
log4j-1.2.16.jar
aspectjrt.jar
aspectjweaver.jar
commons-logging.jar
2.面向切面的Log類:
import org.apache.log4j.Logger; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class LogAspect { Logger logger=Logger.getLogger(LogAspect.class); String logStr=null; /** * 前置通知:在某連接點之前執行的通知,但這個通知不能阻止連接點前的執行 * @param jp 連接點:程序執行過程中的某一行為 */ public void doBefore(JoinPoint jp){ logStr=jp.getTarget().getClass().getName()+"類的" +jp.getSignature().getName()+"方法開始執行******Start******"; logger.info(logger); } /** * 環繞通知:包圍一個連接點的通知,可以在方法的調用前后完成自定義的行為,也可以選擇不執行。 * 類似web中Servlet規范中Filter的doFilter方法。 * @param pjp 當前進程中的連接點 * @return */ public Object doAround(ProceedingJoinPoint pjp){ long Time=System.currentTimeMillis(); Object result=null; try { result=pjp.proceed(); } catch (Throwable e) { e.printStackTrace(); logStr="方法:"+pjp.getTarget().getClass()+"."+pjp.getSignature().getName()+"()"; logStr=logStr+"錯誤信息如下:["+e+"]"; logger.info(logStr); } return result; } /** * 后置通知 * @param jp */ public void doAfter(JoinPoint jp){ logStr=jp.getTarget().getClass().getName()+"類的" +jp.getSignature().getName()+"方法執行結束******End******"; logger.info(logStr); } }
3.spring配置文件ApplicationContext.xml中配置AOP相關日志
<!--AOP類日志 --> <bean id="logAspect" class="yan.joanna.log.LogAspect"></bean> <aop:config> <aop:aspect id="aspect" ref="logAspect"> <!--對哪些方法進行日志記錄,此處屏蔽action內的set get方法 --> <aop:pointcut id="logService" expression="(execution(* yan.joanna.*.*.*(..)) ) and (!execution(* yan.joanna.action.*.set*(..)) ) and (!execution(* yan.joanna.action.*.get*(..)) )" /> <aop:before pointcut-ref="logService" method="doBefore"/> <aop:after pointcut-ref="logService" method="doAfter"/> <aop:around pointcut-ref="logService" method="doAround"/> </aop:aspect> </aop:config> <!-- 配置Action --> <bean id="UserAction" class="yan.joanna.action.UserAction" scope="prototype"> <property name="userDAO" ref="UserDAO"></property> <property name="maindeviceDAO" ref="MaindeviceDAO"></property> <property name="amountDAO" ref="AmountDAO"></property> <property name="deviceUsingDAO" ref="DeviceUsingDAO"></property> </bean>
4.log4j的log4j.properties文件的主要配置
log4j.rootLogger = info, stdout, R
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 = %p %d{yyyy-MM-dd HH:mm:ssS} || %c{1} || %m%n
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=d:/UTrainFileLib/logs/utrain.log
log4j.appender.R.Append=true
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%-d{yyyy-MM-dd HH\:mm\:ss} [%c]-[%p] [%t] (%F\:%L) ->%m %n
log4j.appender.R.Threshold=INFO
log4j.appender.R.DatePattern='.'yyyy-MM-dd
5.在開發或者運行初期,我們可能想打印一些業務邏輯,參數值等,並控制它的打印級別
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class JYLog { private static final Log log = LogFactory.getLog(JYLog.class); public static void printLog(String msg){ if(log.isInfoEnabled()){ log.info(msg); } } public static void errorLog(String msg,Exception e){ log.error(msg, e); } public static void errorLog(String msg){ log.error(msg); } }
6.業務日志的打印,eg:UserAction中的登錄方法:
/** * 登錄 * @throws IOException */ public void login() throws IOException{ HttpServletRequest req=ServletActionContext.getRequest(); HttpServletResponse resp=ServletActionContext.getResponse(); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); String tel=req.getParameter("tel"); JYLog.printLog("login()-登錄-Timestamp-"+new Timestamp(System.currentTimeMillis())+ ";tel-"+tel); PrintWriter out=resp.getWriter(); JSONObject json=new JSONObject(); JSONObject dataJson=new JSONObject(); String message=""; int errorcode=0; if(!"".equals(tel)){ User user=userDAO.findByAccount(tel); if(user==null){ userDAO.save(new User(tel, new Timestamp(System.currentTimeMillis()),new Timestamp(System.currentTimeMillis()), 1)); user=userDAO.findByAccount(tel); amountDAO.save(new Amount(user, 100,0)); }else{ userDAO.updateLoginTime(user); } dataJson.put("id", user.getId()); dataJson.put("account", user.getAccount()); dataJson.put("type", user.getType()); message="登錄成功"; errorcode=0; }else{ message="手機號不合法"; errorcode=10002; } json.put("data", dataJson); json.put("message", message); json.put("errorcode", errorcode); out.print(json); out.flush(); out.close(); JYLog.printLog("login()-登錄-json-"+json.toString()); }
7.日志打印文件內容部分顯示:
[yan.joanna.log.JYLog]-[INFO] [http-bio-59500-exec-56] (JYLog.java:11) ->login()-登錄-Timestamp-2017-04-01 08:10:08.972;tel-15515123456 2017-04-01 08:10:08 [yan.joanna.log.LogAspect]-[INFO] [http-bio-59500-exec-56] (LogAspect.java:14) ->org.apache.log4j.Logger@10fb78e 2017-04-01 08:10:08 [yan.joanna.log.LogAspect]-[INFO] [http-bio-59500-exec-56] (LogAspect.java:34) ->yan.joanna.dao.UserDAO類的findByAccount方法執行結束******End****** 2017-04-01 08:10:08 [yan.joanna.log.LogAspect]-[INFO] [http-bio-59500-exec-56] (LogAspect.java:14) ->org.apache.log4j.Logger@10fb78e 2017-04-01 08:10:08 [yan.joanna.log.LogAspect]-[INFO] [http-bio-59500-exec-56] (LogAspect.java:34) ->yan.joanna.dao.UserDAO類的updateLoginTime方法執行結束******End****** 2017-04-01 08:10:09 [yan.joanna.log.JYLog]-[INFO] [http-bio-59500-exec-56] (JYLog.java:11) ->login()-登錄-json-{"data":{"id":68,"account":"15515123456","type":1},"message":"登錄成功","errorcode":0} 2017-04-01 08:10:09 [yan.joanna.log.LogAspect]-[INFO] [http-bio-59500-exec-56] (LogAspect.java:34) ->yan.joanna.action.UserAction類的login方法執行結束******End******
如果此文對您有幫助,微信打賞我一下吧~