使用 SpringBoot AOP 記錄操作日志、異常日志
來(lái)源:cnblogs.com/wm-dv/p/11735828.html
一、創(chuàng)建日志記錄表、異常日志表,表結(jié)構(gòu)如下: 二、添加Maven依賴 三、創(chuàng)建操作日志注解類OperLog.java 四、創(chuàng)建切面類記錄操作日志 五、在Controller層方法添加@OperLog注解 六、操作日志、異常日志查詢功能
平時(shí)我們?cè)谧鲰?xiàng)目時(shí)經(jīng)常需要對(duì)一些重要功能操作記錄日志,方便以后跟蹤是誰(shuí)在操作此功能;我們?cè)诓僮髂承┕δ軙r(shí)也有可能會(huì)發(fā)生異常,但是每次發(fā)生異常要定位原因我們都要到服務(wù)器去查詢?nèi)罩静拍苷业剑乙膊荒軐?duì)發(fā)生的異常進(jìn)行統(tǒng)計(jì),從而改進(jìn)我們的項(xiàng)目,要是能做個(gè)功能專門來(lái)記錄操作日志和異常日志那就好了, 當(dāng)然我們肯定有方法來(lái)做這件事情,而且也不會(huì)很難,我們可以在需要的方法中增加記錄日志的代碼,和在每個(gè)方法中增加記錄異常的代碼,最終把記錄的日志存到數(shù)據(jù)庫(kù)中。聽起來(lái)好像很容易,但是我們做起來(lái)會(huì)發(fā)現(xiàn),做這項(xiàng)工作很繁瑣,而且都是在做一些重復(fù)性工作,還增加大量冗余代碼,這種方式記錄日志肯定是不可行的。
我們以前學(xué)過(guò)Spring 三大特性,IOC(控制反轉(zhuǎn)),DI(依賴注入),AOP(面向切面),那其中AOP的主要功能就是將日志記錄,性能統(tǒng)計(jì),安全控制,事務(wù)處理,異常處理等代碼從業(yè)務(wù)邏輯代碼中劃分出來(lái)。今天我們就來(lái)用springBoot Aop 來(lái)做日志記錄,好了,廢話說(shuō)了一大堆還是上貨吧。
一、創(chuàng)建日志記錄表、異常日志表,表結(jié)構(gòu)如下:


二、添加Maven依賴
1?<dependency>
2?????<groupId>org.springframework.bootgroupId>
3?????<artifactId>spring-boot-starter-aopartifactId>
4?dependency>
三、創(chuàng)建操作日志注解類OperLog.java
?1?package?com.hyd.zcar.cms.common.utils.annotation;
?2
?3?import?java.lang.annotation.Documented;
?4?import?java.lang.annotation.ElementType;
?5?import?java.lang.annotation.Retention;
?6?import?java.lang.annotation.RetentionPolicy;
?7?import?java.lang.annotation.Target;
?8
?9?/**
10??*?自定義操作日志注解
11??*?@author?wu
12??*/
13?@Target(ElementType.METHOD)?//注解放置的目標(biāo)位置,METHOD是可注解在方法級(jí)別上
14?@Retention(RetentionPolicy.RUNTIME)?//注解在哪個(gè)階段執(zhí)行
15?@Documented
16?public?@interface?OperLog?{
17?????String?operModul()?default?"";?//?操作模塊
18?????String?operType()?default?"";??//?操作類型
19?????String?operDesc()?default?"";??//?操作說(shuō)明
20?}
四、創(chuàng)建切面類記錄操作日志
??1?package?com.hyd.zcar.cms.common.utils.aop;
??2
??3?import?java.lang.reflect.Method;
??4?import?java.util.Date;
??5?import?java.util.HashMap;
??6?import?java.util.Map;
??7
??8?import?javax.servlet.http.HttpServletRequest;
??9
?10?import?org.aspectj.lang.JoinPoint;
?11?import?org.aspectj.lang.annotation.AfterReturning;
?12?import?org.aspectj.lang.annotation.AfterThrowing;
?13?import?org.aspectj.lang.annotation.Aspect;
?14?import?org.aspectj.lang.annotation.Pointcut;
?15?import?org.aspectj.lang.reflect.MethodSignature;
?16?import?org.springframework.beans.factory.annotation.Autowired;
?17?import?org.springframework.beans.factory.annotation.Value;
?18?import?org.springframework.stereotype.Component;
?19?import?org.springframework.web.context.request.RequestAttributes;
?20?import?org.springframework.web.context.request.RequestContextHolder;
?21
?22?import?com.gexin.fastjson.JSON;
?23?import?com.hyd.zcar.cms.common.utils.IPUtil;
?24?import?com.hyd.zcar.cms.common.utils.annotation.OperLog;
?25?import?com.hyd.zcar.cms.common.utils.base.UuidUtil;
?26?import?com.hyd.zcar.cms.common.utils.security.UserShiroUtil;
?27?import?com.hyd.zcar.cms.entity.system.log.ExceptionLog;
?28?import?com.hyd.zcar.cms.entity.system.log.OperationLog;
?29?import?com.hyd.zcar.cms.service.system.log.ExceptionLogService;
?30?import?com.hyd.zcar.cms.service.system.log.OperationLogService;
?31
?32?/**
?33??*?切面處理類,操作日志異常日志記錄處理
?34??*
?35??*?@author?wu
?36??*?@date?2019/03/21
?37??*/
?38?@Aspect
?39?@Component
?40?public?class?OperLogAspect?{
?41
?42?????/**
?43??????*?操作版本號(hào)
?44??????*?
?45 ?????*?項(xiàng)目啟動(dòng)時(shí)從命令行傳入,例如:java -jar xxx.war --version=201902
?46??????*?
?47??????*/
?48?????@Value("${version}")
?49?????private?String?operVer;
?50
?51?????@Autowired
?52?????private?OperationLogService?operationLogService;
?53
?54?????@Autowired
?55?????private?ExceptionLogService?exceptionLogService;
?56
?57?????/**
?58??????*?設(shè)置操作日志切入點(diǎn)?記錄操作日志?在注解的位置切入代碼
?59??????*/
?60?????@Pointcut("@annotation(com.hyd.zcar.cms.common.utils.annotation.OperLog)")
?61?????public?void?operLogPoinCut()?{
?62?????}
?63
?64?????/**
?65??????*?設(shè)置操作異常切入點(diǎn)記錄異常日志?掃描所有controller包下操作
?66??????*/
?67?????@Pointcut("execution(*?com.hyd.zcar.cms.controller..*.*(..))")
?68?????public?void?operExceptionLogPoinCut()?{
?69?????}
?70
?71?????/**
?72??????*?正常返回通知,攔截用戶操作日志,連接點(diǎn)正常執(zhí)行完成后執(zhí)行,?如果連接點(diǎn)拋出異常,則不會(huì)執(zhí)行
?73??????*
?74??????*?@param?joinPoint?切入點(diǎn)
?75??????*?@param?keys??????返回結(jié)果
?76??????*/
?77?????@AfterReturning(value?=?"operLogPoinCut()",?returning?=?"keys")
?78?????public?void?saveOperLog(JoinPoint?joinPoint,?Object?keys)?{
?79?????????//?獲取RequestAttributes
?80?????????RequestAttributes?requestAttributes?=?RequestContextHolder.getRequestAttributes();
?81?????????//?從獲取RequestAttributes中獲取HttpServletRequest的信息
?82?????????HttpServletRequest?request?=?(HttpServletRequest)?requestAttributes
?83?????????????????.resolveReference(RequestAttributes.REFERENCE_REQUEST);
?84
?85?????????OperationLog?operlog?=?new?OperationLog();
?86?????????try?{
?87?????????????operlog.setOperId(UuidUtil.get32UUID());?//?主鍵ID
?88
?89?????????????//?從切面織入點(diǎn)處通過(guò)反射機(jī)制獲取織入點(diǎn)處的方法
?90?????????????MethodSignature?signature?=?(MethodSignature)?joinPoint.getSignature();
?91?????????????//?獲取切入點(diǎn)所在的方法
?92?????????????Method?method?=?signature.getMethod();
?93?????????????//?獲取操作
?94?????????????OperLog?opLog?=?method.getAnnotation(OperLog.class);
?95?????????????if?(opLog?!=?null)?{
?96?????????????????String?operModul?=?opLog.operModul();
?97?????????????????String?operType?=?opLog.operType();
?98?????????????????String?operDesc?=?opLog.operDesc();
?99?????????????????operlog.setOperModul(operModul);?//?操作模塊
100?????????????????operlog.setOperType(operType);?//?操作類型
101?????????????????operlog.setOperDesc(operDesc);?//?操作描述
102?????????????}
103?????????????//?獲取請(qǐng)求的類名
104?????????????String?className?=?joinPoint.getTarget().getClass().getName();
105?????????????//?獲取請(qǐng)求的方法名
106?????????????String?methodName?=?method.getName();
107?????????????methodName?=?className?+?"."?+?methodName;
108
109?????????????operlog.setOperMethod(methodName);?//?請(qǐng)求方法
110
111?????????????//?請(qǐng)求的參數(shù)
112?????????????Map?rtnMap?=?converMap(request.getParameterMap());
113?????????????//?將參數(shù)所在的數(shù)組轉(zhuǎn)換成json
114?????????????String?params?=?JSON.toJSONString(rtnMap);
115
116?????????????operlog.setOperRequParam(params);?//?請(qǐng)求參數(shù)
117?????????????operlog.setOperRespParam(JSON.toJSONString(keys));?//?返回結(jié)果
118?????????????operlog.setOperUserId(UserShiroUtil.getCurrentUserLoginName());?//?請(qǐng)求用戶ID
119?????????????operlog.setOperUserName(UserShiroUtil.getCurrentUserName());?//?請(qǐng)求用戶名稱
120?????????????operlog.setOperIp(IPUtil.getRemortIP(request));?//?請(qǐng)求IP
121?????????????operlog.setOperUri(request.getRequestURI());?//?請(qǐng)求URI
122?????????????operlog.setOperCreateTime(new?Date());?//?創(chuàng)建時(shí)間
123?????????????operlog.setOperVer(operVer);?//?操作版本
124?????????????operationLogService.insert(operlog);
125?????????}?catch?(Exception?e)?{
126?????????????e.printStackTrace();
127?????????}
128?????}
129
130?????/**
131??????*?異常返回通知,用于攔截異常日志信息?連接點(diǎn)拋出異常后執(zhí)行
132??????*
133??????*?@param?joinPoint?切入點(diǎn)
134??????*?@param?e?????????異常信息
135??????*/
136?????@AfterThrowing(pointcut?=?"operExceptionLogPoinCut()",?throwing?=?"e")
137?????public?void?saveExceptionLog(JoinPoint?joinPoint,?Throwable?e)?{
138?????????//?獲取RequestAttributes
139?????????RequestAttributes?requestAttributes?=?RequestContextHolder.getRequestAttributes();
140?????????//?從獲取RequestAttributes中獲取HttpServletRequest的信息
141?????????HttpServletRequest?request?=?(HttpServletRequest)?requestAttributes
142?????????????????.resolveReference(RequestAttributes.REFERENCE_REQUEST);
143
144?????????ExceptionLog?excepLog?=?new?ExceptionLog();
145?????????try?{
146?????????????//?從切面織入點(diǎn)處通過(guò)反射機(jī)制獲取織入點(diǎn)處的方法
147?????????????MethodSignature?signature?=?(MethodSignature)?joinPoint.getSignature();
148?????????????//?獲取切入點(diǎn)所在的方法
149?????????????Method?method?=?signature.getMethod();
150?????????????excepLog.setExcId(UuidUtil.get32UUID());
151?????????????//?獲取請(qǐng)求的類名
152?????????????String?className?=?joinPoint.getTarget().getClass().getName();
153?????????????//?獲取請(qǐng)求的方法名
154?????????????String?methodName?=?method.getName();
155?????????????methodName?=?className?+?"."?+?methodName;
156?????????????//?請(qǐng)求的參數(shù)
157?????????????Map?rtnMap?=?converMap(request.getParameterMap());
158?????????????//?將參數(shù)所在的數(shù)組轉(zhuǎn)換成json
159?????????????String?params?=?JSON.toJSONString(rtnMap);
160?????????????excepLog.setExcRequParam(params);?//?請(qǐng)求參數(shù)
161?????????????excepLog.setOperMethod(methodName);?//?請(qǐng)求方法名
162?????????????excepLog.setExcName(e.getClass().getName());?//?異常名稱
163?????????????excepLog.setExcMessage(stackTraceToString(e.getClass().getName(),?e.getMessage(),?e.getStackTrace()));?//?異常信息
164?????????????excepLog.setOperUserId(UserShiroUtil.getCurrentUserLoginName());?//?操作員ID
165?????????????excepLog.setOperUserName(UserShiroUtil.getCurrentUserName());?//?操作員名稱
166?????????????excepLog.setOperUri(request.getRequestURI());?//?操作URI
167?????????????excepLog.setOperIp(IPUtil.getRemortIP(request));?//?操作員IP
168?????????????excepLog.setOperVer(operVer);?//?操作版本號(hào)
169?????????????excepLog.setOperCreateTime(new?Date());?//?發(fā)生異常時(shí)間
170
171?????????????exceptionLogService.insert(excepLog);
172
173?????????}?catch?(Exception?e2)?{
174?????????????e2.printStackTrace();
175?????????}
176
177?????}
178
179?????/**
180??????*?轉(zhuǎn)換request?請(qǐng)求參數(shù)
181??????*
182??????*?@param?paramMap?request獲取的參數(shù)數(shù)組
183??????*/
184?????public?Map?converMap(Map?paramMap) ? {
185?????????Map?rtnMap?=?new?HashMap();
186?????????for?(String?key?:?paramMap.keySet())?{
187?????????????rtnMap.put(key,?paramMap.get(key)[0]);
188?????????}
189?????????return?rtnMap;
190?????}
191
192?????/**
193??????*?轉(zhuǎn)換異常信息為字符串
194??????*
195??????*?@param?exceptionName????異常名稱
196??????*?@param?exceptionMessage?異常信息
197??????*?@param?elements?????????堆棧信息
198??????*/
199?????public?String?stackTraceToString(String?exceptionName,?String?exceptionMessage,?StackTraceElement[]?elements)?{
200?????????StringBuffer?strbuff?=?new?StringBuffer();
201?????????for?(StackTraceElement?stet?:?elements)?{
202?????????????strbuff.append(stet?+?"\n");
203?????????}
204?????????String?message?=?exceptionName?+?":"?+?exceptionMessage?+?"\n\t"?+?strbuff.toString();
205?????????return?message;
206?????}
207?}
五、在Controller層方法添加@OperLog注解

六、操作日志、異常日志查詢功能





-END-
SSM框架權(quán)限系統(tǒng)腳手架教程(資料全)
加我微信回復(fù)“SSM框架權(quán)限”即可獲取
點(diǎn)個(gè)在看!?
謝謝支持喲 (*^__^*)

