SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)

做日志管理最好的是Aop,有的人也喜欢用拦截器。都可以,在此我重点介绍我的实现方式。

Aop有的人说拦截不到Controller。有的人说想拦AnnotationMethodHandlerAdapter截到Controller必须得拦截org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter。

首先Aop可以拦截到Controller的,这个是毋容置疑的其次须拦截AnnotationMethodHandlerAdapter也不是必须的。最起码我没有验证成功过这个。我的spring版本是4.0.3。

Aop之所以有的人说拦截不到Controller是因为Controller被jdk代理了。我们只要把它交给cglib代理就可以了。

第一步定义两个注解:

Java代码 
[java]  view plain  copy
  1. import java.lang.annotation.*;  
  2.   
  3. /** 
  4.  * 自定义注解 拦截Controller 
  5.  */  
  6. @Target({ ElementType.PARAMETER, ElementType.METHOD })  
  7. @Retention(RetentionPolicy.RUNTIME)  
  8. @Documented  
  9. public @interface SystemControllerLog {  
  10.     String description() default "";  
  11. }  

[java]  view plain  copy
  1. import java.lang.annotation.*;  
  2.   
  3. /** 
  4.  * 自定义注解 拦截service 
  5.  */  
  6. @Target({ ElementType.PARAMETER, ElementType.METHOD })  
  7. @Retention(RetentionPolicy.RUNTIME)  
  8. @Documented  
  9. public @interface SystemServiceLog {  
  10.     String description() default "";  
  11. }  


第二步创建一个切点类:

[java]  view plain  copy
  1. package com.cl.web.log.service;  
  2.   
  3. import org.aspectj.lang.JoinPoint;  
  4. import org.aspectj.lang.annotation.*;  
  5. import org.slf4j.Logger;  
  6. import org.slf4j.LoggerFactory;  
  7. import org.springframework.stereotype.Component;  
  8. import org.springframework.web.context.request.RequestContextHolder;  
  9. import org.springframework.web.context.request.ServletRequestAttributes;  
  10.   
  11. import com.cl.common.annotation.SystemControllerLog;  
  12. import com.cl.common.annotation.SystemServiceLog;  
  13. import com.cl.common.constant.Constants;  
  14. import com.cl.common.tool.JSONUtil;  
  15. import com.cl.web.log.entity.OperationLog;  
  16. import com.cl.web.user.entity.User;  
  17.   
  18. import javax.annotation.Resource;  
  19. import javax.servlet.http.HttpServletRequest;  
  20. import javax.servlet.http.HttpSession;  
  21.   
  22. import java.lang.reflect.Method;  
  23. import java.util.Date;  
  24.   
  25. /** 
  26.  * 切点类 
  27.  *  
  28.  * @author tiangai 
  29.  * @since 2014-08-05 Pm 20:35 
  30.  * @version 1.0 
  31.  */  
  32. @Aspect  
  33. @Component  
  34. public class SystemLogAspect {  
  35.     // 注入Service用于把日志保存数据库  
  36.     @Resource  
  37.     private LogService logService;  
  38.     // 本地异常日志记录对象  
  39.     private static final Logger logger = LoggerFactory  
  40.             .getLogger(SystemLogAspect.class);  
  41.   
  42.     // Service层切点  
  43.     @Pointcut("@annotation(com.cl.common.annotation.SystemServiceLog)")  
  44.     public void serviceAspect() {  
  45.     }  
  46.   
  47.     // Controller层切点  
  48.     @Pointcut("@annotation(com.cl.common.annotation.SystemControllerLog)")  
  49.     public void controllerAspect() {  
  50.     }  
  51.   
  52.     /** 
  53.      * 前置通知 用于拦截Controller层记录用户的操作 
  54.      *  
  55.      * @param joinPoint 
  56.      *            切点 
  57.      */  
  58.     @Before("controllerAspect()")  
  59.     public void doBefore(JoinPoint joinPoint) {  
  60.   
  61.         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder  
  62.                 .getRequestAttributes()).getRequest();  
  63.         HttpSession session = request.getSession();  
  64.         // 读取session中的用户  
  65.         User user = (User) session.getAttribute(Constants.CURRENT_USER);  
  66.         // 请求的IP  
  67.         String ip = request.getRemoteAddr();  
  68.         try {  
  69.             // *========控制台输出=========*//  
  70.             System.out.println("=====前置通知开始=====");  
  71.             System.out.println("请求方法:"  
  72.                     + (joinPoint.getTarget().getClass().getName() + "."  
  73.                             + joinPoint.getSignature().getName() + "()"));  
  74.             System.out.println("方法描述:"  
  75.                     + getControllerMethodDescription(joinPoint));  
  76.             // System.out.println("请求人:" + user.getUsername());  
  77.             System.out.println("请求IP:" + ip);  
  78.             // *========数据库日志=========*//  
  79.             OperationLog log = new OperationLog();  
  80.             log.setDescription(getControllerMethodDescription(joinPoint));  
  81.             log.setMethod((joinPoint.getTarget().getClass().getName() + "."  
  82.                     + joinPoint.getSignature().getName() + "()"));  
  83.             log.setIp(ip);  
  84.             log.setParams(null);  
  85.             log.setOperationDate(new Date());  
  86.             // 保存数据库  
  87.             logService.add(log);  
  88.             System.out.println("=====前置通知结束=====");  
  89.         } catch (Exception e) {  
  90.             logger.error("异常信息:{}", e.getMessage());  
  91.         }  
  92.     }  
  93.   
  94.     /** 
  95.      * 异常通知 用于拦截service层记录异常日志 
  96.      *  
  97.      * @param joinPoint 
  98.      * @param e 
  99.      */  
  100.     @AfterThrowing(pointcut = "serviceAspect()", throwing = "e")  
  101.     public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {  
  102.         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder  
  103.                 .getRequestAttributes()).getRequest();  
  104.         HttpSession session = request.getSession();  
  105.         // 读取session中的用户  
  106.         User user = (User) session.getAttribute(Constants.CURRENT_USER);  
  107.         // 获取请求ip  
  108.         String ip = request.getRemoteAddr();  
  109.         // 获取用户请求方法的参数并序列化为JSON格式字符串  
  110.         String params = "";  
  111.         if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {  
  112.             for (int i = 0; i < joinPoint.getArgs().length; i++) {  
  113.                 params += JSONUtil.toJson(joinPoint.getArgs()[i]) + ";";  
  114.             }  
  115.         }  
  116.         try {  
  117.             /* ========控制台输出========= */  
  118.             System.out.println("=====异常通知开始=====");  
  119.             System.out.println("异常代码:" + e.getClass().getName());  
  120.             System.out.println("异常信息:" + e.getMessage());  
  121.             System.out.println("异常方法:"  
  122.                     + (joinPoint.getTarget().getClass().getName() + "."  
  123.                             + joinPoint.getSignature().getName() + "()"));  
  124.             System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));  
  125.             System.out.println("请求人:" + user.getUsername());  
  126.             System.out.println("请求IP:" + ip);  
  127.             System.out.println("请求参数:" + params);  
  128.             /* ==========数据库日志========= */  
  129.             OperationLog log = new OperationLog();  
  130.             log.setDescription(getControllerMethodDescription(joinPoint));  
  131.             log.setMethod((joinPoint.getTarget().getClass().getName() + "."  
  132.                     + joinPoint.getSignature().getName() + "()"));  
  133.             log.setIp(ip);  
  134.             log.setParams(params);  
  135.             log.setOperationDate(new Date());  
  136.             // 保存数据库  
  137.             logService.add(log);  
  138.             System.out.println("=====异常通知结束=====");  
  139.         } catch (Exception ex) {  
  140.             logger.error("异常信息:{}", ex.getMessage());  
  141.         }  
  142.         logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget()  
  143.                 .getClass().getName()  
  144.                 + joinPoint.getSignature().getName(), e.getClass().getName(),  
  145.                 e.getMessage(), params);  
  146.   
  147.     }  
  148.   
  149.     /** 
  150.      * 获取注解中对方法的描述信息 用于service层注解 
  151.      *  
  152.      * @param joinPoint 
  153.      *            切点 
  154.      * @return 方法描述 
  155.      * @throws Exception 
  156.      */  
  157.     public static String getServiceMthodDescription(JoinPoint joinPoint)  
  158.             throws Exception {  
  159.         String targetName = joinPoint.getTarget().getClass().getName();  
  160.         String methodName = joinPoint.getSignature().getName();  
  161.         Object[] arguments = joinPoint.getArgs();  
  162.         Class targetClass = Class.forName(targetName);  
  163.         Method[] methods = targetClass.getMethods();  
  164.         String description = "";  
  165.         for (Method method : methods) {  
  166.             if (method.getName().equals(methodName)) {  
  167.                 Class[] clazzs = method.getParameterTypes();  
  168.                 if (clazzs.length == arguments.length) {  
  169.                     description = method.getAnnotation(SystemServiceLog.class)  
  170.                             .description();  
  171.                     break;  
  172.                 }  
  173.             }  
  174.         }  
  175.         return description;  
  176.     }  
  177.   
  178.     /** 
  179.      * 获取注解中对方法的描述信息 用于Controller层注解 
  180.      *  
  181.      * @param joinPoint 
  182.      *            切点 
  183.      * @return 方法描述 
  184.      * @throws Exception 
  185.      */  
  186.     public static String getControllerMethodDescription(JoinPoint joinPoint)  
  187.             throws Exception {  
  188.         String targetName = joinPoint.getTarget().getClass().getName();  
  189.         String methodName = joinPoint.getSignature().getName();  
  190.         Object[] arguments = joinPoint.getArgs();  
  191.         Class targetClass = Class.forName(targetName);  
  192.         Method[] methods = targetClass.getMethods();  
  193.         String description = "";  
  194.         for (Method method : methods) {  
  195.             if (method.getName().equals(methodName)) {  
  196.                 Class[] clazzs = method.getParameterTypes();  
  197.                 if (clazzs.length == arguments.length) {  
  198.                     description = method.getAnnotation(  
  199.                             SystemControllerLog.class).description();  
  200.                     break;  
  201.                 }  
  202.             }  
  203.         }  
  204.         return description;  
  205.     }  
  206. }  




第三步把Controller的代理权交给cglib

在实例化ApplicationContext的时候需要加上

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <!– 启动对@AspectJ注解的支持 –>  
  2. <aop:aspectj-autoproxy/>  

在调用Controller的时候AOP发挥作用所以在SpringMVC的配置文件里加上

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <!–通知spring使用cglib而不是jdk的来生成代理方法 AOP可以拦截到Controller->  
  2. <aop:aspectj-autoproxy proxy-target-class=”true” />  

第四步使用

Controller层的使用

Java代码 
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.     * 删除用户 
  3.     * 
  4.     * @param criteria 条件 
  5.     * @param id       id 
  6.     * @param model    模型 
  7.     * @return 数据列表 
  8.     */  
  9.    @RequestMapping(value = ”/delete”)  
  10.    //此处为记录AOP拦截Controller记录用户操作  
  11.    @SystemControllerLog(description = ”删除用户”)  
  12.     public String del(Criteria criteria, String id, Model model, HttpSession session) {  
  13.         try {  
  14.            User user = (User) session.getAttribute(WebConstants.CURRENT_USER);  
  15.             if ( null != user) {  
  16.                 if (user.getId().equals(id)) {  
  17.                    msg = ”您不可以删除自己!”;  
  18.                    criteria = userService.selectByCriteriaPagination(criteria);  
  19.                }  else {  
  20.                    //删除数据并查询出数据  
  21.                    criteria = userService.delete(id, criteria);  
  22.                    msg = ”删除成功!”;  
  23.                }  
  24.            }  
  25.        }  catch (Exception e) {  
  26.            msg = ”删除失败!”;  
  27.        }  finally {  
  28.            model.addAttribute(“msg”, msg);  
  29.            model.addAttribute(“criteria”, criteria);  
  30.        }  
  31.        //跳转列表页  
  32.         return ”user/list”;  
  33.    }  

Service层的使用

Java代码 
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.     * 按照分页查询 
  3.     * @param criteria 
  4.     * @return 
  5.     */  
  6.    //此处为AOP拦截Service记录异常信息。方法不需要加try-catch  
  7.    @SystemServiceLog(description = ”查询用户”)  
  8.     public Criteria<User> selectByCriteriaPagination(Criteria<User> criteria)  
  9.    {  
  10.        criteria.getList().get(0).getAccount();  
  11.        //查询总数  
  12.         long total=userMapper.countByCriteria(criteria);  
  13.        //设置总数  
  14.        criteria.setRowCount(total);  
  15.        criteria.setList(userMapper.selectByCriteriaPagination(criteria));  
  16.         return  criteria;  
  17.    }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值