日志拦截AOP,当执行抛异常时@AfterThrowing执行了没效果


使用Spring的AOP进行日志记录,对应的代码为

[java] view plain copy
  1. package cn.tiansu.eway.logAop;  
  2.   
  3. import java.lang.reflect.Method;  
  4. import java.util.HashMap;  
  5. import java.util.Map;  
  6.   
  7. import javax.inject.Inject;  
  8.   
  9. import org.apache.shiro.SecurityUtils;  
  10. import org.aspectj.lang.JoinPoint;  
  11. import org.aspectj.lang.ProceedingJoinPoint;  
  12. import org.aspectj.lang.annotation.AfterThrowing;  
  13. import org.aspectj.lang.annotation.Around;  
  14. import org.aspectj.lang.annotation.Aspect;  
  15. import org.aspectj.lang.annotation.Pointcut;  
  16. import org.slf4j.Logger;  
  17. import org.slf4j.LoggerFactory;  
  18. import org.springframework.core.Ordered;  
  19. import org.springframework.stereotype.Component;  
  20.   
  21. import cn.tiansu.eway.annotation.SystemLog;  
  22. import cn.tiansu.eway.entity.LogFormMap;  
  23. import cn.tiansu.eway.mapper.LogMapper;  
  24. import cn.tiansu.eway.util.Common;  
  25.   
  26. /** 
  27.  * 切点类 
  28.  * 
  29.  * @author LJN 
  30.  * @since 2015-05-05 Pm 20:35 
  31.  * @version 1.0 
  32.  */  
  33. @Aspect  
  34. @Component  
  35. public class LogAopAction <span style="color:#ff0000;">implements Ordered</span>{  
  36.     // 本地异常日志记录对象  
  37.     private static final Logger logger = LoggerFactory.getLogger(LogAopAction.class);  
  38.     @Inject  
  39.     private LogMapper logMapper;  
  40.   
  41.     // Controller层切点  
  42.     @Pointcut("@annotation(cn.tiansu.eway.annotation.SystemLog)")  
  43.     public void controllerAspect() {  
  44.     }  
  45.   
  46.     /** 
  47.      * 操作异常记录 
  48.      * 
  49.      * @descript 
  50.      * @param point 
  51.      * @param e 
  52.      * @author LJN 
  53.      * @date 2015年5月5日 
  54.      * @version 1.0 
  55.      */  
  56.     @AfterThrowing(pointcut = "controllerAspect()", throwing = "e")  
  57.     public void doAfterThrowing(JoinPoint point, Throwable e) {  
  58.         LogFormMap logForm = new LogFormMap();  
  59.         Map<String, Object> map = null;  
  60.         String user = null;  
  61.         String ip = null;  
  62.         Long start = 0L;  
  63.         Long end = 0L;  
  64.         Long time = 0L;  
  65.         try {  
  66.             ip = SecurityUtils.getSubject().getSession().getHost();  
  67.         } catch (Exception ee) {  
  68.             ip = "无法获取登录用户Ip";  
  69.         }  
  70.         try {  
  71.             map = getControllerMethodDescription(point);  
  72.             // 登录名  
  73.             user = SecurityUtils.getSubject().getPrincipal().toString();  
  74.             if (Common.isEmpty(user)) {  
  75.                 user = "无法获取登录用户信息!";  
  76.             }  
  77.         } catch (Exception ee) {  
  78.             user = "无法获取登录用户信息!";  
  79.         }  
  80.   
  81.         try {  
  82.             start = System.currentTimeMillis();  
  83.             end = System.currentTimeMillis();  
  84.             time = end - start;  
  85.   
  86.             logForm.put("accountName", user);  
  87.             logForm.put("module", map.get("module"));  
  88.             logForm.put("methods", map.get("methods"));  
  89.             logForm.put("description""执行失败,原因:" + e);  
  90.             logForm.put("actionTime", time);  
  91.             logForm.put("userIP", ip);  
  92.             logForm.put("type", map.get("type"));  
  93.             logMapper.addEntity(logForm);  
  94.   
  95.         } catch (Exception e1) {  
  96.             e1.printStackTrace();  
  97.         }  
  98.     }  
  99.   
  100.     /** 
  101.      * 前置通知 用于拦截Controller层记录用户的操作 
  102.      * 
  103.      * @param joinPoint 
  104.      *            切点 
  105.      */  
  106.     @Around("controllerAspect()")  
  107.     public Object doController(ProceedingJoinPoint point) {  
  108.         Object result = null;  
  109.         // 执行方法名  
  110.         String methodName = point.getSignature().getName();  
  111.         String className = point.getTarget().getClass().getSimpleName();  
  112.         LogFormMap logForm = new LogFormMap();  
  113.         Map<String, Object> map = null;  
  114.         String user = null;  
  115.         Long start = 0L;  
  116.         Long end = 0L;  
  117.         Long time = 0L;  
  118.         String ip = null;  
  119.         try {  
  120.             ip = SecurityUtils.getSubject().getSession().getHost();  
  121.         } catch (Exception e) {  
  122.             ip = "无法获取登录用户Ip";  
  123.         }  
  124.         try {  
  125.             // 登录名  
  126.             user = SecurityUtils.getSubject().getPrincipal().toString();  
  127.             if (Common.isEmpty(user)) {  
  128.                 user = "无法获取登录用户信息!";  
  129.             }  
  130.         } catch (Exception e) {  
  131.             user = "无法获取登录用户信息!";  
  132.         }  
  133.         // 当前用户  
  134.         try {  
  135.             map = getControllerMethodDescription(point);  
  136.             // 执行方法所消耗的时间  
  137.             start = System.currentTimeMillis();  
  138.             result = point.proceed();  
  139.             end = System.currentTimeMillis();  
  140.             time = end - start;  
  141.         } catch (Throwable e) {  
  142.             throw new RuntimeException(e);  
  143.         }  
  144.         try {  
  145.             logForm.put("accountName", user);  
  146.             logForm.put("module", map.get("module"));  
  147.             logForm.put("methods", map.get("methods"));  
  148.             logForm.put("type", map.get("type"));  
  149.             logForm.put("description", map.get("description"));  
  150.             logForm.put("actionTime", time.toString());  
  151.             logForm.put("userIP", ip);  
  152.             logMapper.addEntity(logForm);  
  153.             // *========控制台输出=========*//  
  154.             System.out.println("=====通知开始=====");  
  155.             System.out.println("请求方法:" + className + "." + methodName + "()");  
  156.             System.out.println("方法描述:" + map);  
  157.             System.out.println("请求IP:" + ip);  
  158.             System.out.println("=====通知结束=====");  
  159.         } catch (Exception e) {  
  160.             // 记录本地异常日志  
  161.             logger.error("====通知异常====");  
  162.             logger.error("异常信息:{}", e.getMessage());  
  163.         }  
  164.         return result;  
  165.     }  
  166.   
  167.     /** 
  168.      * 获取注解中对方法的描述信息 用于Controller层注解 
  169.      * 
  170.      * @param joinPoint 
  171.      *            切点 
  172.      * @return 方法描述 
  173.      * @throws Exception 
  174.      */  
  175.     @SuppressWarnings("rawtypes")  
  176.     public Map<String, Object> getControllerMethodDescription(  
  177.             JoinPoint joinPoint) throws Exception {  
  178.         Map<String, Object> map = new HashMap<String, Object>();  
  179.         String targetName = joinPoint.getTarget().getClass().getName();  
  180.         String methodName = joinPoint.getSignature().getName();  
  181.         Object[] arguments = joinPoint.getArgs();  
  182.         Class targetClass = Class.forName(targetName);  
  183.         Method[] methods = targetClass.getMethods();  
  184.         for (Method method : methods) {  
  185.             if (method.getName().equals(methodName)) {  
  186.                 Class[] clazzs = method.getParameterTypes();  
  187.                 if (clazzs.length == arguments.length) {  
  188.                     map.put("module", method.getAnnotation(SystemLog.class)  
  189.                             .module());  
  190.                     map.put("methods", method.getAnnotation(SystemLog.class)  
  191.                             .methods());  
  192.                     map.put("type", method.getAnnotation(SystemLog.class)  
  193.                             .type());  
  194.                     String de = method.getAnnotation(SystemLog.class)  
  195.                             .description();  
  196.                     if (Common.isEmpty(de))  
  197.                         de = "执行成功!";  
  198.                     map.put("description", de);  
  199.                     break;  
  200.                 }  
  201.             }  
  202.         }  
  203.         return map;  
  204.     }  
  205.   
  206.     <span style="color:#ff0000;">@Override  
  207.     public int getOrder() {  
  208.         // TODO Auto-generated method stub  
  209.         return 1;  
  210.     }</span>  
  211. }  
当执行正常时,走 @Around;当执行异常时,走@AfterThrowing。结果发现,执行异常时,@AfterThrowing方法正常执行完毕,但是异常日志并没有插入数据表中,插入日志的代码也没报任何错误,遂百度之(http://my.oschina.net/HuifengWang/blog/304188),发现问题所在:

Spring中的事务是通过aop来实现的,当我们自己写aop拦截的时候,会遇到跟spring的事务aop执行的先后顺序问题,比如说动态切换数据源的问题,如果事务在前,数据源切换在后,会导致数据源切换失效,所以就用到了Order(排序)这个关键字.我们可以通过在@AspectJ的方法中实现org.springframework.core.Ordered 这个接口来定义order的顺序,order 的值越小,说明越先被执行。

当实现Ordered 接口之后,我们自己写的aop在事务介入之前就执行了!

猜你喜欢

转载自blog.csdn.net/u014756578/article/details/79563385
今日推荐