日誌攔截AOP,當執行拋異常時@AfterThrowing執行了沒效果
阿新 • • 發佈:2019-02-12
使用Spring的AOP進行日誌記錄,對應的程式碼為
- package cn.tiansu.eway.logAop;
- import java.lang.reflect.Method;
- import java.util.HashMap;
- import java.util.Map;
- import javax.inject.Inject;
- import org.apache.shiro.SecurityUtils;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.AfterThrowing;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.core.Ordered;
- import org.springframework.stereotype.Component;
- import cn.tiansu.eway.annotation.SystemLog;
- import cn.tiansu.eway.entity.LogFormMap;
- import cn.tiansu.eway.mapper.LogMapper;
- import cn.tiansu.eway.util.Common;
- /**
- * 切點類
- *
- * @author LJN
- * @since 2015-05-05 Pm 20:35
- * @version 1.0
- */
- @Aspect
- @Component
- publicclass LogAopAction <span style="color:#ff0000;">implements Ordered</span>{
- // 本地異常日誌記錄物件
- privatestaticfinal Logger logger = LoggerFactory.getLogger(LogAopAction.class);
- @Inject
- private LogMapper logMapper;
- // Controller層切點
- @Pointcut("@annotation(cn.tiansu.eway.annotation.SystemLog)")
- publicvoid controllerAspect() {
- }
- /**
- * 操作異常記錄
- *
- * @descript
- * @param point
- * @param e
- * @author LJN
- * @date 2015年5月5日
- * @version 1.0
- */
- @AfterThrowing(pointcut = "controllerAspect()", throwing = "e")
- publicvoid doAfterThrowing(JoinPoint point, Throwable e) {
- LogFormMap logForm = new LogFormMap();
- Map<String, Object> map = null;
- String user = null;
- String ip = null;
- Long start = 0L;
- Long end = 0L;
- Long time = 0L;
- try {
- ip = SecurityUtils.getSubject().getSession().getHost();
- } catch (Exception ee) {
- ip = "無法獲取登入使用者Ip";
- }
- try {
- map = getControllerMethodDescription(point);
- // 登入名
- user = SecurityUtils.getSubject().getPrincipal().toString();
- if (Common.isEmpty(user)) {
- user = "無法獲取登入使用者資訊!";
- }
- } catch (Exception ee) {
- user = "無法獲取登入使用者資訊!";
- }
- try {
- start = System.currentTimeMillis();
- end = System.currentTimeMillis();
- time = end - start;
- logForm.put("accountName", user);
- logForm.put("module", map.get("module"));
- logForm.put("methods", map.get("methods"));
- logForm.put("description", "執行失敗,原因:" + e);
- logForm.put("actionTime", time);
- logForm.put("userIP", ip);
- logForm.put("type", map.get("type"));
- logMapper.addEntity(logForm);
- } catch (Exception e1) {
- e1.printStackTrace();
- }
- }
- /**
- * 前置通知 用於攔截Controller層記錄使用者的操作
- *
- * @param joinPoint
- * 切點
- */
- @Around("controllerAspect()")
- public Object doController(ProceedingJoinPoint point) {
- Object result = null;
- // 執行方法名
- String methodName = point.getSignature().getName();
- String className = point.getTarget().getClass().getSimpleName();
- LogFormMap logForm = new LogFormMap();
- Map<String, Object> map = null;
- String user = null;
- Long start = 0L;
- Long end = 0L;
- Long time = 0L;
- String ip = null;
- try {
- ip = SecurityUtils.getSubject().getSession().getHost();
- } catch (Exception e) {
- ip = "無法獲取登入使用者Ip";
- }
- try {
- // 登入名
- user = SecurityUtils.getSubject().getPrincipal().toString();
- if (Common.isEmpty(user)) {
- user = "無法獲取登入使用者資訊!";
- }
- } catch (Exception e) {
- user = "無法獲取登入使用者資訊!";
- }
- // 當前使用者
- try {
- map = getControllerMethodDescription(point);
- // 執行方法所消耗的時間
- start = System.currentTimeMillis();
- result = point.proceed();
- end = System.currentTimeMillis();
- time = end - start;
- } catch (Throwable e) {
- thrownew RuntimeException(e);
- }
- try {
- logForm.put("accountName", user);
- logForm.put("module", map.get("module"));
- logForm.put("methods", map.get("methods"));
- logForm.put("type", map.get("type"));
- logForm.put("description", map.get("description"));
- logForm.put("actionTime", time.toString());
- logForm.put("userIP", ip);
- logMapper.addEntity(logForm);
- // *========控制檯輸出=========*//
- System.out.println("=====通知開始=====");
- System.out.println("請求方法:" + className + "." + methodName + "()");
- System.out.println("方法描述:" + map);
- System.out.println("請求IP:" + ip);
- System.out.println("=====通知結束=====");
- } catch (Exception e) {
- // 記錄本地異常日誌
- logger.error("====通知異常====");
- logger.error("異常資訊:{}", e.getMessage());
- }
- return result;
- }
- /**
- * 獲取註解中對方法的描述資訊 用於Controller層註解
- *
- * @param joinPoint
- * 切點
- * @return 方法描述
- * @throws Exception
- */
- @SuppressWarnings("rawtypes")
- public Map<String, Object> getControllerMethodDescription(
- JoinPoint joinPoint) throws Exception {
- Map<String, Object> map = new HashMap<String, Object>();
- String targetName = joinPoint.getTarget().getClass().getName();
- String methodName = joinPoint.getSignature().getName();
- Object[] arguments = joinPoint.getArgs();
- Class targetClass = Class.forName(targetName);
- Method[] methods = targetClass.getMethods();
- for (Method method : methods) {
- if (method.getName().equals(methodName)) {
- Class[] clazzs = method.getParameterTypes();
- if (clazzs.length == arguments.length) {
- map.put("module", method.getAnnotation(SystemLog.class)
- .module());
- map.put("methods", method.getAnnotation(SystemLog.class)
- .methods());
- map.put("type", method.getAnnotation(SystemLog.class)
- .type());
- String de = method.getAnnotation(SystemLog.class)
- .description();
- if (Common.isEmpty(de))
- de = "執行成功!";
- map.put("description", de);
- break;
- }
- }
- }
- return map;
- }
- <span style="color:#ff0000;">@Override
- publicint getOrder() {
- // TODO Auto-generated method stub
- return1;
- }</span>
- }
Spring中的事務是通過aop來實現的,當我們自己寫aop攔截的時候,會遇到跟spring的事務aop執行的先後順序問題,比如說動態切換資料來源的問題,如果事務在前,資料來源切換在後,會導致資料來源切換失效,所以就用到了Order(排序)這個關鍵字.我們可以通過在@AspectJ的方法中實現org.springframework.core.Ordered 這個介面來定義order的順序,order 的值越小,說明越先被執行。
當實現Ordered 介面之後,我們自己寫的aop在事務介入之前就執行了!