用aspectJ 做了一次日志

1、

Java代码  

  1. <aspectj.version>1.7.4.RELEASE</aspectj.version>
  2. <dependency>
  3. <groupId>org.aspectj</groupId>
  4. <artifactId>aspectjweaver</artifactId>
  5. <version>${aspectj.version}</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.aspectj</groupId>
  9. <artifactId>aspectjrt</artifactId>
  10. <version>${aspectj.version}</version>
  11. </dependency>

注意:如果JDK1.7的 必须这里也是1.7+

2、

Java代码  

  1. <aop:config proxy-target-class="true"></aop:config>
  2. <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
  3. <property name="securityManager" ref="securityManager"/>
  4. </bean>
  5. <aop:aspectj-autoproxy proxy-target-class="true"/>

注意:下载 必须在spring-mvc.xml里面,且有两个aop配置,下面那个是必须的,上面那个可能不是必须的(上面那个应该是spring aop的,如果有aspectJ了,可以不需要)

3、AOP类

Java代码  

  1. package com.kingen.aop;
  2. import java.lang.reflect.Method;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.transaction.Transactional;
  5. import org.aspectj.lang.JoinPoint;
  6. import org.aspectj.lang.annotation.AfterReturning;
  7. import org.aspectj.lang.annotation.AfterThrowing;
  8. import org.aspectj.lang.annotation.Aspect;
  9. import org.aspectj.lang.annotation.Pointcut;
  10. import org.slf4j.Logger;
  11. import org.slf4j.LoggerFactory;
  12. import org.springframework.stereotype.Component;
  13. import org.springframework.util.Assert;
  14. import org.springframework.web.context.request.RequestContextHolder;
  15. import org.springframework.web.context.request.ServletRequestAttributes;
  16. import com.kingen.bean.Log;
  17. import com.kingen.bean.User;
  18. import com.kingen.service.log.LogService;
  19. import com.kingen.util.Constants;
  20. import com.kingen.util.DateUtils;
  21. import com.kingen.util.SpringContextHolder;
  22. import com.kingen.util.StringUtils;
  23. import com.kingen.util.UserUtils;
  24. /**
  25. * 日志AOP
  26. *
  27. * @author wj
  28. * @date 2016-11-16
  29. *
  30. */
  31. @Aspect
  32. @Component
  33. public class LogAOP {
  34. private static LogService logService = SpringContextHolder.getBean(LogService.class);
  35. 下载
  36. // 本地异常日志记录对象
  37. private Logger logger = LoggerFactory.getLogger(getClass());
  38. /**
  39. * 在所有标注@LogAnnotation的地方切入
  40. *
  41. * @param joinPoint
  42. */
  43. @Pointcut("@annotation(com.kingen.aop.LogAnnotation)")
  44. public void logAspect() {
  45. }
  46. // @Around(value = "aApplogic() && @annotation(annotation) &&args(object,..)
  47. // ", argNames = "annotation,object")
  48. // public Object around(ProceedingJoinPoint pj,
  49. // LogAnnotation annotation, Object object) throws Throwable {
  50. // System.out.println("moduleName:"+annotation.moduleName());
  51. // System.out.println("option:"+annotation.option());
  52. // pj.proceed();
  53. // return object;
  54. // }
  55. /**
  56. * 前置通知 用于拦截Controller层记录用户的操作
  57. *
  58. * @param joinPoint
  59. *            切点
  60. * @throws Exception
  61. */
  62. //  @Around(value = "logAspect() && @annotation(annotation) &&args(object,..) ", argNames = "annotation,object")
  63. //  public void doAround(ProceedingJoinPoint joinPoint, LogAnnotation annotation, Object object) {
  64. //用@Around 会导致controller不执行,不返回页面
  65. //   @After(value = "logAspect() && @annotation(annotation) &&args(object,..) ", argNames = "annotation,object")
  66. //   public void doAfter(JoinPoint joinPoint, LogAnnotation annotation, Object object) {
  67. @AfterReturning(value = "logAspect() && @annotation(annotation) &&args(object,..) ", argNames = "", returning = "retVal")
  68. public void doAfterReturning(JoinPoint joinPoint, LogAnnotation annotation, Object object,  String retVal) {
  69. HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
  70. .getRequest();
  71. try {
  72. // String title = getAnnotationValue(joinPoint);
  73. String title = getAnnotationValue(annotation);
  74. saveLog(request, title);
  75. } catch (Exception e) {
  76. e.printStackTrace();
  77. // 记录本地异常日志
  78. logger.error("==异常通知异常==");
  79. logger.error("异常信息:{}", e.getMessage());
  80. }
  81. }
  82. /**
  83. * 异常通知 用于拦截service层记录异常日志
  84. *
  85. * @param joinPoint
  86. * @param e
  87. */
  88. // 方法  catch住异常的话,这里执行不到
  89. //  @AfterThrowing(pointcut = "logAspect()", throwing = "e")
  90. @AfterThrowing(value = "logAspect() && @annotation(annotation) &&args(..) " , throwing = "e")
  91. public void doAfterThrowing(JoinPoint joinPoint,  LogAnnotation annotation, Exception e) {
  92. HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
  93. .getRequest();
  94. try {
  95. //          String title = getAnnotationValue(joinPoint);
  96. String title = getAnnotationValue(annotation);
  97. saveLog(request, title, e);
  98. } catch (Exception ex) {
  99. // 记录本地异常日志
  100. logger.error("==异常通知异常==");
  101. logger.error("异常信息:{}", ex.getMessage());
  102. }
  103. }
  104. 下载
  105. public static void saveLog(HttpServletRequest request, String title) {
  106. saveLog(request, title, null);
  107. }
  108. /**
  109. * 保存日志
  110. */
  111. @Transactional
  112. public static void saveLog(HttpServletRequest request, String title, Exception ex) {
  113. User user = UserUtils.getCurrentUser();
  114. if (user != null && user.getUserId() != null) {
  115. Log log = new Log();
  116. log.setCreateDate(DateUtils.getDateTime());
  117. log.setTitle(title);
  118. log.setType(ex == null ? Log.TYPE_ACCESS : Log.TYPE_EXCEPTION);
  119. log.setRemoteAddr(StringUtils.getRemoteAddr(request));
  120. log.setUserAgent(user.getUsername());
  121. // log.setUserAgent(request.getHeader("user-agent"));
  122. log.setRequestUri(request.getRequestURI());
  123. log.setParams(request.getParameterMap());
  124. // 如果有异常,设置异常信息
  125. log.setException(ex == null ? null : ex.getMessage());
  126. //          log.setException(ex == null ? null : Exceptions.getStackTraceAsString(ex));
  127. log.setStatus(ex == null ? Constants.StatusEnum.Success.getIndex() : Constants.StatusEnum.Fail.getIndex());
  128. // log.setMethod(request.getMethod());
  129. // 异步保存日志
  130. // new SaveLogThread(log, handler, ex).start();
  131. logService.saveLog(log);
  132. }
  133. }
  134. /**
  135. * 获取注解中对方法的描述信息 用于Controller层注解
  136. *
  137. * @param joinPoint
  138. *            切点
  139. * @return 方法描述
  140. * @throws Exception
  141. */
  142. @Deprecated
  143. public static String getAnnotationValue(JoinPoint joinPoint) throws Exception {
  144. String targetName = joinPoint.getTarget().getClass().getName();
  145. String methodName = joinPoint.getSignature().getName();
  146. Object[] arguments = joinPoint.getArgs();
  147. Class targetClass = Class.forName(targetName);
  148. Method[] methods = targetClass.getMethods();
  149. String description = "";
  150. for (Method method : methods) {
  151. if (method.getName().equals(methodName)) {
  152. Class[] clazzs = method.getParameterTypes();
  153. if (clazzs.length == arguments.length) {
  154. String moduleName = method.getAnnotation(LogAnnotation.class).moduleName();
  155. String option = method.getAnnotation(LogAnnotation.class).option();
  156. Assert.hasText(moduleName, "模块名字不应为空");
  157. Assert.hasText(option, "操作名字不应为空");
  158. description = moduleName + "-" + option;
  159. break;
  160. }
  161. }
  162. }
  163. return description;
  164. }
  165. public static String getAnnotationValue(LogAnnotation anno) throws Exception {
  166. String moduleName = anno.moduleName();
  167. String option = anno.option();
  168. Assert.hasText(moduleName, "模块名字不应为空");
  169. Assert.hasText(option, "操作名字不应为空");
  170. String description = moduleName + "-" + option;
  171. return description;
  172. }
  173. }

注意这里 @After和 @AfterReturning的区别,总的来说,就是 @After 是无论如何都会执行的,不管有没有异常抛出(这样会导致,在有异常的时候,记录两次日志,after一次、throwing一次);@AfterReturning 在有异常的情况下,不会执行到,因为没有renturn,在retrun之前就throw了。

时间: 2024-10-20 12:08:20

用aspectJ 做了一次日志的相关文章

方法级别的java日志输出控制(二)集群

在方法级别的java日志输出控制(一)这篇文章中主要讨论了通过properties配置文件以及AOP技术批量控制方法级别的日志输出. 用properties配置文件的好处是不用更改程序即可控制日志的输出,然而大型的应用通常是分布式的,会有很多的服务器,需要更改全部服务器上的配置文件,然后再重启应用.这将会是一件非常麻烦的事情.事实上在大型集群应用中有更好的方法实现他.zookeeper的特性决定着它有一个应用场景就是集群配置中心.本文不介绍zookeeper原理以及搭建,将直接使用zookeep

Elasticsearch慢查询日志分析

目前架构: n台filebeat客户端来将每台应用上的日志传到kafka,3台kafka做集群用于日志队列,四台ES做集群,前两台存放近两天热数据日志,后两台存放两天前的历史日志,数据保存一个月,目前总数据量6T.logstash与kibana与ES在一台机器上,kibana访问域名三个kibana做轮询, 目前ELK中发现有些索引查询有点慢,于是打开ES索引查询日志来记录慢查询,进而对慢查询日志进行分析,定位问题.慢日志内容如下: [2017-08-28T11:21:02,377][WARN 

日志收集系统 ELK

查看日志一直都是一个很困扰的问题,登录到服务器上查看几百兆的txt文件,从中找到某个问题可能会留下的日志记录......   尤其是现在,在集群式部署的服务器原来越多的时候,找到一个异常记录几乎要翻遍每一台服务器,想想就崩溃了!这个时候就特别希望能有一个集中查看日志的方案来拯救我. 曾经找到一个名为log4Grid的项目,试用了一下.日志数据都保存到mssql数据库中,通过一个web项目来查询显示日志记录.只是实现了基本的日志数据收集和显示,项目没有持续更新,使用起来也不够稳定.不是一个成熟的日

打造高效的运维日志收集与分析平台

0x01 背景      面对与日俱增的日志信息,最传统的日志收集方式已难以满足运维人员的基本需求.So,我们何不利用如今丰富的开源工具来打造一款高效实用的运维日志收集分析平台呢.以下就我们目前尝试在做的运维日志平台进行简要介绍,希望能与各位交流心得经验. 0x02 平台架构     我们并没有采用ELK的架构进行日志收集,而是采用了多款日志收集工具结合的方式,即EKF(K/Z), elasticsearch + kafka-zookeeper + Flume + kibana/zabbix.

java程序日志管理

初入软件开发这一行的人,可能对日志管理的概念并不是很明确,大概是由于经验所限,以至于根本还考虑不到这个问题. 而从某种意义上来说,日志管理实际上也不需要初入这一行的人来管,他们只需要负责实现自己的主要业务逻辑和功能就好了. 我当初刚入行的时候就有很长一段时间完全不用去关心日志,到后来偶尔涉及到的时候,也都是从其他地方采用cv大法直接搬用. 不过,随着工作时间的变化,随着手头上任务重要程度的变化,也随着接触到的项目数量的变化,让我越来越意识到日志的重要性,它在整个系统中发挥着至关重要的作用! 尤其

日志传送

背景:腾讯云服务器与本地数据库服务器做日志传送,其中腾讯云做为主体.日志传送,关键要解决的是传送的问题.本例主.备服务器不在同一个局域网,不能用Windows文件共享的方式传输日志文件.考虑利用ftp.rsync.fastcopy工具完成文件的异地传送.1.[辅助数据库服务器]配置rsync从主数据库服务器的D:\LogShipping目录,获取备份文件到辅助数据库服务器的D:\LogShipping目录:创建任务计划,让rsync每隔5分钟重复一次,每次获取新增的备份文件2.[辅助数据库服务器

实时收集Storm日志到ELK集群

背景 我们的storm实时流计算项目已经上线几个月了,由于各种原因迟迟没有进行监控,每次出现问题都要登录好几台机器,然后使用sed,shell,awk,vi等各种命令来查询原因,效率非常低下,而且有些统计是没法做的,所以很有必要对storm本身相关的日志以及我们运行在storm上面的任务的日志做一个统一的日志收集,分析,查询,统计平台. 技术选型 对于这个选择,其实不用考虑那么多,借用一句名言 Life is short , You need elk ! 关于elk相关的安装这里不再介绍,可参考

SignalR实现实时日志监控

.net SignalR实现实时日志监控 摘要 昨天吃饭的时候,突然想起来一个好玩的事,如果能有个页面可以实时的监控网站或者其他类型的程序的日志,其实也不错.当然,网上也有很多成熟的类似的监控系统.就想着如果通过.net该如何实现?所以就在想,通过系统内部将消息推送到前端,.net中可以通过pull或者push的方式,pull通常的做法就是ajax方式不停的请求一个接口,这种方式,不太理想.然后就在想如何通过服务端想客户端推送消息.之前看到过SignalR方面的文章可以实现push的功能,sig

MySQL 日志管理

一.MySQL 日志 日志是mysql数据库的重要组成部分.日志文件中记录着mysql数据库运行期间发生的变化:也就是说用来记录mysql数据库的客户端连接状况.SQL语句的执行情况和错误信息等.当数据库遭到意外的损坏时,可以通过日志查看文件出错的原因,并且可以通过日志文件进行数据恢复. MySQL 日志类型: 主要包含:错误日志.查询日志.慢查询日志.事务日志.二进制日志: 错误日志 一般查询日志: DML, SELECT, 对于非常繁忙的数据库,会产生大量的日志 慢查询日志:执行时间很慢的查