第一次使用aspectj记录

一.使用原因

        需求是,在增、删、改时记录用户的ID、被操作数据的ID,并插入数据库

二、开发过程


        比较坎坷。以前只是知道有这种方法,但怎么实现却是第一次。

        首先,参考的是: http://blog.csdn.net/paincupid/article/details/50534412
        
        pom中引入

        
   
   
  1. <!--使用AspectJ方式注解需要相应的包-->
  2. <dependency>
  3. <groupId>org.aspectj</groupId>
  4. <artifactId>aspectjrt</artifactId>
  5. <version>${aspectj.version}</version>
  6. </dependency>
  7. <!--使用AspectJ方式注解需要相应的包-->
  8. <dependency>
  9. <groupId>org.aspectj</groupId>
  10. <artifactId>aspectjweaver</artifactId>
  11. <version>${aspectj.version}</version>
  12. </dependency>


        1.编写注解@interface


        
   
   
  1. package com.ufgov.util.opelog;
  2. import java.lang.annotation.*;
  3. /**
  4. * @author lihhz
  5. * @mail lihhz@yonyou.com
  6. * @company http://www.yonyou.com
  7. * @date 2017/7/12
  8. */
  9. @Retention(RetentionPolicy.RUNTIME)//注解会在class中存在,运行时可通过反射获取
  10. @Target(ElementType.METHOD)//目标是方法
  11. @Documented//文档生成时,该注解将被包含在javadoc中,可去掉
  12. public @interface SysOpeLogInf {
  13. // String id() default "-1";
  14. String valueKey();
  15. Class<?> clazz();
  16. enum OpeType {
  17. ADD, UPD, DEL
  18. }
  19. OpeType type() default OpeType.ADD;
  20. }


        2.编写切面

   
   
  1. package com.ufgov.util.opelog;
  2. import com.ufgov.entity.SysOpeLog;
  3. import com.ufgov.entity.SysRole;
  4. import com.ufgov.entity.SysUserInfo;
  5. import com.ufgov.mapper.SysOpeLogMapper;
  6. import com.ufgov.util.DateUtils;
  7. import com.ufgov.util.MemcachedUtils;
  8. import com.ufgov.util.ToolClass;
  9. import com.ufgov.util.UUIDUtil;
  10. import org.aspectj.lang.JoinPoint;
  11. import org.aspectj.lang.Signature;
  12. import org.aspectj.lang.annotation.*;
  13. import org.aspectj.lang.reflect.MethodSignature;
  14. import org.slf4j.Logger;
  15. import org.slf4j.LoggerFactory;
  16. import org.springframework.beans.factory.annotation.Autowired;
  17. import org.springframework.web.context.request.RequestAttributes;
  18. import org.springframework.web.context.request.RequestContextHolder;
  19. import org.springframework.web.context.request.ServletRequestAttributes;
  20. import javax.servlet.http.HttpServletRequest;
  21. import java.lang.annotation.Annotation;
  22. import java.lang.reflect.Field;
  23. import java.lang.reflect.Method;
  24. /**
  25. * @author lihhz
  26. * @mail lihhz@yonyou.com
  27. * @company http://www.yonyou.com
  28. * @date 2017/7/12
  29. */
  30. @Aspect
  31. //@Component
  32. public class SysOpeLogAspect {
  33. private static final Logger logger = LoggerFactory.getLogger(SysOpeLogAspect.class);
  34. @Autowired
  35. private SysOpeLogMapper sysOpeLogMapper;
  36. private String oldKey,newKey;
  37. enum WHEN{
  38. BEFORE,AFTER,AFTER_THROWING
  39. }
  40. @Pointcut("@annotation(com.ufgov.util.opelog.SysOpeLogInf)")
  41. public void controllerAspect() {
  42. }
  43. @Before("controllerAspect()")
  44. public void doBefore(JoinPoint joinPoint) {
  45. System.out.println("=====SysLogAspect前置通知开始=====");
  46. handleOpeLog(joinPoint,WHEN.BEFORE);
  47. }
  48. @AfterReturning(pointcut="controllerAspect()")
  49. public void doAfter(JoinPoint joinPoint) {
  50. System.out.println("=====SysLogAspect后置通知开始=====");
  51. handleOpeLog(joinPoint,WHEN.AFTER);
  52. oldKey=null;newKey=null;
  53. }
  54. @AfterThrowing(value="controllerAspect()",throwing="e")
  55. public void doAfter(JoinPoint joinPoint, Exception e) {
  56. System.out.println("=====SysLogAspect异常通知开始=====");
  57. e.printStackTrace();
  58. // handleOpeLog(joinPoint,WHEN.AFTER_THROWING);
  59. }
  60. private void handleOpeLog(JoinPoint joinPoint, WHEN w) {//,Exception e
  61. try {
  62. //获得注解
  63. SysOpeLogInf logger = giveController(joinPoint);
  64. if(logger == null)return;
  65. MethodSignature signature = (MethodSignature)joinPoint.getSignature();
  66. String signatureStr = signature.toString(); // 获取目标方法签名
  67. String methodName = signatureStr.substring(signatureStr.lastIndexOf(".") + 1,signatureStr.indexOf("("));
  68. // String longTemp = joinPoint.getStaticPart().toLongString();
  69. String classType = joinPoint.getTarget().getClass().getName();
  70. Class<?> clazz = Class.forName(classType);
  71. Method[] methods = clazz.getDeclaredMethods();
  72. for (Method method : methods) {
  73. Object targetObject = null;
  74. if (method.isAnnotationPresent(SysOpeLogInf.class) && method.getName().equals(methodName)) {
  75. // Annotation[][] annotations = method.getParameterAnnotations();
  76. Annotation annotation = method.getAnnotation(SysOpeLogInf.class);
  77. SysOpeLogInf l = (SysOpeLogInf) annotation;
  78. Object[] args = joinPoint.getArgs();
  79. for (Object tmpObject : args) {
  80. if(l.clazz() != null && l.clazz() == tmpObject.getClass()){
  81. targetObject = tmpObject;
  82. }
  83. // Object tmpObject = args[i];
  84. // if (annotations.length > 0) {
  85. // for (Annotation annotation : annotations[i]) {
  86. // if (annotation.annotationType() == SysOpeLogInf.class) {
  87. // }
  88. // }
  89. // }
  90. }
  91. RequestAttributes ra = RequestContextHolder.getRequestAttributes();
  92. ServletRequestAttributes sra = (ServletRequestAttributes) ra;
  93. HttpServletRequest request = sra.getRequest();
  94. SysUserInfo userInfo = MemcachedUtils.getUserInfo(request);
  95. SysRole roleInfo = MemcachedUtils.getRoleInfo(request);
  96. String opeType = "新增",desc;
  97. boolean isContinue = false;
  98. switch (l.type()) {
  99. case ADD:
  100. isContinue = addOrUpd(w,request,l,targetObject);
  101. break;
  102. case DEL:
  103. isContinue = true;
  104. opeType = "删除";
  105. oldKey = request.getParameter(l.valueKey());
  106. // desc = oldKey + "#删除";
  107. break;
  108. case UPD:
  109. opeType = "修改";
  110. isContinue = addOrUpd(w,request,l,targetObject);
  111. break;
  112. }
  113. if(isContinue) {
  114. desc = opeType + "#oldKey=" + oldKey;
  115. if(l.type() != SysOpeLogInf.OpeType.DEL) {
  116. if(!oldKey.equals(newKey)){
  117. opeType = "新增";
  118. }
  119. desc = desc + "#newKey=" + newKey;
  120. }
  121. SysOpeLog opeLog = new SysOpeLog();
  122. opeLog.setId(UUIDUtil.uuidRandom());
  123. opeLog.setConfirmdesc(desc);
  124. opeLog.setIp(ToolClass.getIp(request));
  125. opeLog.setOpobj(oldKey);
  126. opeLog.setOptime(DateUtils.getTime());
  127. opeLog.setOpobjtype(opeType);
  128. opeLog.setTs(DateUtils.getTime());
  129. opeLog.setRole(roleInfo.getRoleName());
  130. opeLog.setUserId(userInfo.getUserId());
  131. opeLog.setUserName(userInfo.getUserName());
  132. sysOpeLogMapper.insert(opeLog);
  133. }
  134. }
  135. }
  136. } catch (Exception exp) {
  137. logger.error("异常信息:{}", exp.getMessage());
  138. exp.printStackTrace();
  139. }
  140. }
  141. private static SysOpeLogInf giveController(JoinPoint joinPoint) throws Exception {
  142. Signature signature = joinPoint.getSignature();
  143. MethodSignature methodSignature = (MethodSignature) signature;
  144. Method method = methodSignature.getMethod();
  145. if (method != null) {
  146. return method.getAnnotation(SysOpeLogInf.class);
  147. }
  148. return null;
  149. }
  150. // public void insertLogSuccess(JoinPoint jp, SysOpeLogInf logger) {}
  151. //
  152. // public void writeLogInfo(JoinPoint joinPoint, SysOpeLogInf opLogger)
  153. // throws Exception, IllegalAccessException {}
  154. private boolean addOrUpd (WHEN w,HttpServletRequest request,SysOpeLogInf l,Object targetObject) throws Exception{
  155. boolean isContinue = false;
  156. switch (w) {
  157. case BEFORE:
  158. oldKey = request.getParameter(l.valueKey());
  159. break;
  160. case AFTER:
  161. if(targetObject != null){
  162. Field field = targetObject.getClass().getDeclaredField(l.valueKey());
  163. field.setAccessible(true); // 参数值为true,禁止访问控制检查
  164. Object id = field.get(targetObject);
  165. newKey = id.toString();
  166. }else{
  167. newKey = request.getParameter(l.valueKey());
  168. }
  169. isContinue = true;
  170. break;
  171. }
  172. return isContinue;
  173. }
  174. }

            3.在spring-mvc配置文件中配置

   
   
  1. <!-- 启用aop -->
  2. <aop:aspectj-autoproxy proxy-target-class="true" />
  3. <bean class="com.ufgov.util.opelog.SysOpeLogAspect" />
                        要记得加入对应的xmlns等。
   
   
  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns:context="http://www.springframework.org/schema/context"
  4. xmlns:mvc="http://www.springframework.org/schema/mvc"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xsi:schemaLocation="
  7. http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
  9. http://www.springframework.org/schema/context
  10. http://www.springframework.org/schema/context/spring-context-3.2.xsd
  11. http://www.springframework.org/schema/mvc
  12. http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
  13. http://www.springframework.org/schema/aop
  14. http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
  15. http://www.springframework.org/schema/util
  16. http://www.springframework.org/schema/util/spring-util-3.2.xsd">


三、注意点


        1.在spring配置文件中配置aspectj


                需要注意的是在applicationContext中配置如下代码,那么设置将无法生效。参考资料: http://bbs.csdn.net/topics/391049202?page=1
                
   
   
  1. <!-- 启用aop -->
  2. <aop:aspectj-autoproxy proxy-target-class="true" />
  3. <bean class="com.ufgov.util.opelog.SysOpeLogAspect" />
            
                查看网上的资料,原因大概是spring mvc的影响(具体原因待查,不过应该还controller还有service的扫描位置有关            系),需要将上边的配置写在spring-mvc配置文件中

        2.切面执行两次


                在编写切面的时候写了注解@Component造成的。在网上查找,各种不一样的说法,暂时也不是很清楚,待查。总之,我的解决办法是注释@Component即可。参考 http://blog.csdn.net/u014396256/article/details/72771520


         3.关于java的自定义注解



                因为以前几乎没有使用到,所以对这一块几乎不懂。都是网上找到的资料,主要用在了编写@interface中


          4.spring的execution表达式


                    这个比java的自定义注解了解的还少。主要是参考: http://sishuok.com/forum/posts/list/281.html


          5.在切面中获取request


                    参考: http://www.cnblogs.com/softidea/p/5904833.html
                     代码片段如下:
   
   
  1. RequestAttributes ra = RequestContextHolder.getRequestAttributes();
  2. ServletRequestAttributes sra = (ServletRequestAttributes) ra;
  3. HttpServletRequest request = sra.getRequest();

             6.拦截器

                       使用拦截器似乎可以实现一样的效果,还没有试过。

              7.异常处理

        
   
   
  1. java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut myMethod
我遇到的上述异常,解决办法是,提高aspectj的版本。网上也有说可以用降低jdk版本来解决


四、写在最后的话

1.谢谢网友的分享


以前,很少在网上发帖,都是上网查了之后哦自己笔记到本地。最近有了分享的觉悟,开始一点点的在网上分享自己遇到的问题,学到的知识。这些问题大都是借鉴了他人,加了些自己的拙见。希望对他人会有一些帮助

2.spring的拦截器及切面


功能很强大,但是使用到的机会却不多。需要自己多多实践

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值