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

 

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

首先我们为什么需要做日志管理,在现实的上线中我们经常会遇到系统出现异常或者问题。这个时候就马上打开CRT或者SSH连上服务器拿日志来分析。受网络的各种限制。于是我们就想为什么不能直接在管理后台查看报错的信息呢。于是日志管理就出现了。

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

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

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

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

第一步定义两个注解:

1.  package com.annotation;    

2.      

3.  import java.lang.annotation.*;    

4.      

5.  /**  

6.   *自定义注解 拦截Controller  

7.   */    

8.      

9.  @Target({ElementType.PARAMETER, ElementType.METHOD})    

10. @Retention(RetentionPolicy.RUNTIME)    

11. @Documented    

12. public  @interface SystemControllerLog {    

13.     

14.     String description()  default "";    

15.     

16.     

17. }    

18.     

19. package com.annotation;    

20.     

21. import java.lang.annotation.*;    

22.     

23. /**  

24.  *自定义注解 拦截service  

25.  */    

26.     

27. @Target({ElementType.PARAMETER, ElementType.METHOD})    

28. @Retention(RetentionPolicy.RUNTIME)    

29. @Documented    

30. public  @interface SystemServiceLog {    

31.     

32.     String description()  default "";    

33.     

34.     

35. }    

 

第二步创建一个切点类:

 

[java] view plain copy

1.  package com.annotation;    

2.      

3.  import com.model.Log;    

4.  import com.model.User;    

5.  import com.service.LogService;    

6.  import com.util.DateUtil;    

7.  import com.util.JSONUtil;    

8.  import com.util.SpringContextHolder;    

9.  import com.util.WebConstants;    

10. import org.aspectj.lang.JoinPoint;    

11. import org.aspectj.lang.annotation.*;    

12. import org.slf4j.Logger;    

13. import org.slf4j.LoggerFactory;    

14. import org.springframework.stereotype.Component;    

15. import org.springframework.web.context.request.RequestContextHolder;    

16. import org.springframework.web.context.request.ServletRequestAttributes;    

17. import javax.annotation.Resource;    

18. import javax.servlet.http.HttpServletRequest;    

19. import javax.servlet.http.HttpSession;    

20. import java.lang.reflect.Method;    

21.     

22. /**  

23.  * 切点类  

24.  * @author tiangai  

25.  * @since 2014-08-05 Pm 20:35  

26.  * @version 1.0  

27.  */    

28. @Aspect    

29. @Component    

30. public  class SystemLogAspect {    

31.     //注入Service用于把日志保存数据库    

32.     @Resource    

33.      private LogService logService;    

34.     //本地异常日志记录对象    

35.      private  static  final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);    

36.     

37.     //Service层切点    

38.     @Pointcut("@annotation(com.annotation.SystemServiceLog)")    

39.      public  void serviceAspect() {    

40.     }    

41.     

42.     //Controller层切点    

43.     @Pointcut("@annotation(com.annotation.SystemControllerLog)")    

44.      public  void controllerAspect() {    

45.     }    

46.     

47.     /**  

48.      * 前置通知 用于拦截Controller层记录用户的操作  

49.      *  

50.      * @param joinPoint 切点  

51.      */    

52.     @Before("controllerAspect()")    

53.      public  void doBefore(JoinPoint joinPoint) {    

54.     

55.         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();    

56.         HttpSession session = request.getSession();    

57.         //读取session中的用户    

58.         User user = (User) session.getAttribute(WebConstants.CURRENT_USER);    

59.         //请求的IP    

60.         String ip = request.getRemoteAddr();    

61.          try {    

62.             //*========控制台输出=========*//    

63.             System.out.println("=====前置通知开始=====");    

64.             System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    

65.             System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));    

66.             System.out.println("请求人:" + user.getName());    

67.             System.out.println("请求IP:" + ip);    

68.             //*========数据库日志=========*//    

69.             Log log = SpringContextHolder.getBean("logxx");    

70.             log.setDescription(getControllerMethodDescription(joinPoint));    

71.             log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    

72.             log.setType("0");    

73.             log.setRequestIp(ip);    

74.             log.setExceptionCode( null);    

75.             log.setExceptionDetail( null);    

76.             log.setParams( null);    

77.             log.setCreateBy(user);    

78.             log.setCreateDate(DateUtil.getCurrentDate());    

79.             //保存数据库    

80.             logService.add(log);    

81.             System.out.println("=====前置通知结束=====");    

82.         }  catch (Exception e) {    

83.             //记录本地异常日志    

84.             logger.error("==前置通知异常==");    

85.             logger.error("异常信息:{}", e.getMessage());    

86.         }    

87.     }    

88.     

89.     /**  

90.      * 异常通知 用于拦截service层记录异常日志  

91.      *  

92.      * @param joinPoint  

93.      * @param e  

94.      */    

95.     @AfterThrowing(pointcut = "serviceAspect()", throwing = "e")    

96.      public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {    

97.         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();    

98.         HttpSession session = request.getSession();    

99.         //读取session中的用户    

100.          User user = (User) session.getAttribute(WebConstants.CURRENT_USER);    

101.          //获取请求ip    

102.          String ip = request.getRemoteAddr();    

103.          //获取用户请求方法的参数并序列化为JSON格式字符串    

104.          String params = "";    

105.           if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {    

106.               for ( int i = 0; i < joinPoint.getArgs().length; i++) {    

107.                  params += JSONUtil.toJsonString(joinPoint.getArgs()[i]) + ";";    

108.              }    

109.          }    

110.           try {    

111.                /*========控制台输出=========*/    

112.              System.out.println("=====异常通知开始=====");    

113.              System.out.println("异常代码:" + e.getClass().getName());    

114.              System.out.println("异常信息:" + e.getMessage());    

115.              System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    

116.              System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));    

117.              System.out.println("请求人:" + user.getName());    

118.              System.out.println("请求IP:" + ip);    

119.              System.out.println("请求参数:" + params);    

120.                 /*==========数据库日志=========*/    

121.              Log log = SpringContextHolder.getBean("logxx");    

122.              log.setDescription(getServiceMthodDescription(joinPoint));    

123.              log.setExceptionCode(e.getClass().getName());    

124.              log.setType("1");    

125.              log.setExceptionDetail(e.getMessage());    

126.              log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    

127.              log.setParams(params);    

128.              log.setCreateBy(user);    

129.              log.setCreateDate(DateUtil.getCurrentDate());    

130.              log.setRequestIp(ip);    

131.              //保存数据库    

132.              logService.add(log);    

133.              System.out.println("=====异常通知结束=====");    

134.          }  catch (Exception ex) {    

135.              //记录本地异常日志    

136.              logger.error("==异常通知异常==");    

137.              logger.error("异常信息:{}", ex.getMessage());    

138.          }    

139.           /*==========记录本地异常日志==========*/    

140.          logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);    

141.      

142.      }    

143.      

144.      

145.      /**  

146.       * 获取注解中对方法的描述信息 用于service层注解  

147.       *  

148.       * @param joinPoint 切点  

149.       * @return 方法描述  

150.       * @throws Exception  

151.       */    

152.       public  static String getServiceMthodDescription(JoinPoint joinPoint)    

153.               throws Exception {    

154.          String targetName = joinPoint.getTarget().getClass().getName();    

155.          String methodName = joinPoint.getSignature().getName();    

156.          Object[] arguments = joinPoint.getArgs();    

157.          Class targetClass = Class.forName(targetName);    

158.          Method[] methods = targetClass.getMethods();    

159.          String description = "";    

160.           for (Method method : methods) {    

161.               if (method.getName().equals(methodName)) {    

162.                  Class[] clazzs = method.getParameterTypes();    

163.                   if (clazzs.length == arguments.length) {    

164.                      description = method.getAnnotation(SystemServiceLog. class).description();    

165.                       break;    

166.                  }    

167.              }    

168.          }    

169.           return description;    

170.      }    

171.      

172.      /**  

173.       * 获取注解中对方法的描述信息 用于Controller层注解  

174.       *  

175.       * @param joinPoint 切点  

176.       * @return 方法描述  

177.       * @throws Exception  

178.       */    

179.       public  static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {    

180.          String targetName = joinPoint.getTarget().getClass().getName();    

181.          String methodName = joinPoint.getSignature().getName();    

182.          Object[] arguments = joinPoint.getArgs();    

183.          Class targetClass = Class.forName(targetName);    

184.          Method[] methods = targetClass.getMethods();    

185.          String description = "";    

186.           for (Method method : methods) {    

187.               if (method.getName().equals(methodName)) {    

188.                  Class[] clazzs = method.getParameterTypes();    

189.                   if (clazzs.length == arguments.length) {    

190.                      description = method.getAnnotation(SystemControllerLog. class).description();    

191.                       break;    

192.                  }    

193.              }    

194.          }    

195.           return description;    

196.      }    

197.  }    



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

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

 

Xml代码 

1.     <!-- 启动对@AspectJ注解的支持 -->  

2.     <aop:aspectj-autoproxy/>  

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

 

Xml代码 

1.     <!--通知spring使用cglib而不是jdk的来生成代理方法 AOP可以拦截到Controller->  

2.     <aop:aspectj-autoproxy proxy-target-class="true" />  

 第四步使用

 

Controller层的使用

Java代码

[java] view plain copy

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] view plain copy

 

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.    }    

18.  效果图

19.   

20.  用户操作:

21. 

 
异常

22. 

 

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值