第一次使用aspectj记录
2017-07-13 15:43
543 查看
一.使用原因
需求是,在增、删、改时记录用户的ID、被操作数据的ID,并插入数据库
二、开发过程
比较坎坷。以前只是知道有这种方法,但怎么实现却是第一次。首先,参考的是:http://blog.csdn.net/paincupid/article/details/50534412
pom中引入
<!--使用AspectJ方式注解需要相应的包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!--使用AspectJ方式注解需要相应的包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
1.编写注解@interface
package com.ufgov.util.opelog;
import java.lang.annotation.*;
/**
* @author lihhz
* @mail lihhz@yonyou.com
* @company http://www.yonyou.com[/code]* @date 2017/7/12*/@Retention(RetentionPolicy.RUNTIME)//注解会在class中存在,运行时可通过反射获取@Target(ElementType.METHOD)//目标是方法@Documented//文档生成时,该注解将被包含在javadoc中,可去掉public @interface SysOpeLogInf {// String id() default "-1";String valueKey();Class<?> clazz();enum OpeType {ADD, UPD, DEL}OpeType type() default OpeType.ADD;}
2.编写切面package com.ufgov.util.opelog;import com.ufgov.entity.SysOpeLog;import com.ufgov.entity.SysRole;import com.ufgov.entity.SysUserInfo;import com.ufgov.mapper.SysOpeLogMapper;import com.ufgov.util.DateUtils;import com.ufgov.util.MemcachedUtils;import com.ufgov.util.ToolClass;import com.ufgov.util.UUIDUtil;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.Signature;import org.aspectj.lang.annotation.*;import org.aspectj.lang.reflect.MethodSignature;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.context.request.RequestAttributes;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;import java.lang.annotation.Annotation;import java.lang.reflect.Field;import java.lang.reflect.Method;/*** @author lihhz* @mail lihhz@yonyou.com* @company http://www.yonyou.com[/code]* @date 2017/7/12*/@Aspect//@Componentpublic class SysOpeLogAspect {private static final Logger logger = LoggerFactory.getLogger(SysOpeLogAspect.class);@Autowiredprivate SysOpeLogMapper sysOpeLogMapper;private String oldKey,newKey;enum WHEN{BEFORE,AFTER,AFTER_THROWING}@Pointcut("@annotation(com.ufgov.util.opelog.SysOpeLogInf)")public void controllerAspect() {}@Before("controllerAspect()")public void doBefore(JoinPoint joinPoint) {System.out.println("=====SysLogAspect前置通知开始=====");handleOpeLog(joinPoint,WHEN.BEFORE);}@AfterReturning(pointcut="controllerAspect()")public void doAfter(JoinPoint joinPoint) {System.out.println("=====SysLogAspect后置通知开始=====");handleOpeLog(joinPoint,WHEN.AFTER);oldKey=null;newKey=null;}@AfterThrowing(value="controllerAspect()",throwing="e")public void doAfter(JoinPoint joinPoint, Exception e) {System.out.println("=====SysLogAspect异常通知开始=====");e.printStackTrace();// handleOpeLog(joinPoint,WHEN.AFTER_THROWING);}private void handleOpeLog(JoinPoint joinPoint, WHEN w) {//,Exception etry {//获得注解SysOpeLogInf logger = giveController(joinPoint);if(logger == null)return;MethodSignature signature = (MethodSignature)joinPoint.getSignature();String signatureStr = signature.toString(); // 获取目标方法签名String methodName = signatureStr.substring(signatureStr.lastIndexOf(".") + 1,signatureStr.indexOf("("));// String longTemp = joinPoint.getStaticPart().toLongString();String classType = joinPoint.getTarget().getClass().getName();Class<?> clazz = Class.forName(classType);Method[] methods = clazz.getDeclaredMethods();for (Method method : methods) {Object targetObject = null;if (method.isAnnotationPresent(SysOpeLogInf.class) && method.getName().equals(methodName)) {// Annotation[][] annotations = method.getParameterAnnotations();Annotation annotation = method.getAnnotation(SysOpeLogInf.class);SysOpeLogInf l = (SysOpeLogInf) annotation;Object[] args = joinPoint.getArgs();for (Object tmpObject : args) {if(l.clazz() != null && l.clazz() == tmpObject.getClass()){targetObject = tmpObject;}// Object tmpObject = args[i];// if (annotations.length > 0) {// for (Annotation annotation : annotations[i]) {// if (annotation.annotationType() == SysOpeLogInf.class) {//}//}//}}RequestAttributes ra = RequestContextHolder.getRequestAttributes();ServletRequestAttributes sra = (ServletRequestAttributes) ra;HttpServletRequest request = sra.getRequest();SysUserInfo userInfo = MemcachedUtils.getUserInfo(request);SysRole roleInfo = MemcachedUtils.getRoleInfo(request);String opeType = "新增",desc;boolean isContinue = false;switch (l.type()) {case ADD:isContinue = addOrUpd(w,request,l,targetObject);break;case DEL:isContinue = true;opeType = "删除";oldKey = request.getParameter(l.valueKey());// desc = oldKey + "#删除";break;case UPD:opeType = "修改";isContinue = addOrUpd(w,request,l,targetObject);break;}if(isContinue) {desc = opeType + "#oldKey=" + oldKey;if(l.type() != SysOpeLogInf.OpeType.DEL) {if(!oldKey.equals(newKey)){opeType = "新增";}desc = desc + "#newKey=" + newKey;}SysOpeLog opeLog = new SysOpeLog();opeLog.setId(UUIDUtil.uuidRandom());opeLog.setConfirmdesc(desc);opeLog.setIp(ToolClass.getIp(request));opeLog.setOpobj(oldKey);opeLog.setOptime(DateUtils.getTime());opeLog.setOpobjtype(opeType);opeLog.setTs(DateUtils.getTime());opeLog.setRole(roleInfo.getRoleName());opeLog.setUserId(userInfo.getUserId());opeLog.setUserName(userInfo.getUserName());sysOpeLogMapper.insert(opeLog);}}}} catch (Exception exp) {logger.error("异常信息:{}", exp.getMessage());exp.printStackTrace();}}private static SysOpeLogInf giveController(JoinPoint joinPoint) throws Exception {Signature signature = joinPoint.getSignature();MethodSignature methodSignature = (MethodSignature) signature;Method method = methodSignature.getMethod();if (method != null) {return method.getAnnotation(SysOpeLogInf.class);}return null;}// public void insertLogSuccess(JoinPoint jp, SysOpeLogInf logger) {}//// public void writeLogInfo(JoinPoint joinPoint, SysOpeLogInf opLogger)// throws Exception, IllegalAccessException {}private boolean addOrUpd (WHEN w,HttpServletRequest request,SysOpeLogInf l,Object targetObject) throws Exception{boolean isContinue = false;switch (w) {case BEFORE:oldKey = request.getParameter(l.valueKey());break;case AFTER:if(targetObject != null){Field field = targetObject.getClass().getDeclaredField(l.valueKey());field.setAccessible(true); // 参数值为true,禁止访问控制检查Object id = field.get(targetObject);newKey = id.toString();}else{newKey = request.getParameter(l.valueKey());}isContinue = true;break;}return isContinue;}}
3.在spring-mvc配置文件中配置<!-- 启用aop --><aop:aspectj-autoproxy proxy-target-class="true" /><bean class="com.ufgov.util.opelog.SysOpeLogAspect" />
要记得加入对应的xmlns等。<beans xmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans[/code]http://www.springframework.org/schema/beans/spring-beans-3.2.xsd[/code]http://www.springframework.org/schema/context[/code]http://www.springframework.org/schema/context/spring-context-3.2.xsd[/code]http://www.springframework.org/schema/mvc[/code]http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd[/code]http://www.springframework.org/schema/aop[/code]http://www.springframework.org/schema/aop/spring-aop-3.2.xsd[/code]http://www.springframework.org/schema/util[/code]http://www.springframework.org/schema/util/spring-util-3.2.xsd">[/code]
三、注意点需要注意的是在applicationContext中配置如下代码,那么设置将无法生效。参考资料:http://bbs.csdn.net/topics/391049202?page=1
1.在spring配置文件中配置aspectj
<!-- 启用aop --><aop:aspectj-autoproxy proxy-target-class="true" /><bean class="com.ufgov.util.opelog.SysOpeLogAspect" />
查看网上的资料,原因大概是spring mvc的影响(具体原因待查,不过应该还controller还有service的扫描位置有关 系),需要将上边的配置写在spring-mvc配置文件中在编写切面的时候写了注解@Component造成的。在网上查找,各种不一样的说法,暂时也不是很清楚,待查。总之,我的解决办法是注释@Component即可。参考http://blog.csdn.net/u014396256/article/details/72771520
2.切面执行两次参考:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html
3.关于java的自定义注解
因为以前几乎没有使用到,所以对这一块几乎不懂。都是网上找到的资料,主要用在了编写@interface中这个比java的自定义注解了解的还少。主要是参考:http://sishuok.com/forum/posts/list/281.html
4.spring的execution表达式
http://blog.csdn.net/peng658890/article/details/7223046参考:http://www.cnblogs.com/softidea/p/5904833.html
5.在切面中获取request
代码片段如下:RequestAttributes ra = RequestContextHolder.getRequestAttributes();ServletRequestAttributes sra = (ServletRequestAttributes) ra;HttpServletRequest request = sra.getRequest();使用拦截器似乎可以实现一样的效果,还没有试过。
6.拦截器
7.异常处理java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut myMethod
我遇到的上述异常,解决办法是,提高aspectj的版本。网上也有说可以用降低jdk版本来解决四、写在最后的话
1.谢谢网友的分享
以前,很少在网上发帖,都是上网查了之后哦自己笔记到本地。最近有了分享的觉悟,开始一点点的在网上分享自己遇到的问题,学到的知识。这些问题大都是借鉴了他人,加了些自己的拙见。希望对他人会有一些帮助2.spring的拦截器及切面
功能很强大,但是使用到的机会却不多。需要自己多多实践
相关文章推荐
- 使用Spring AOP 的@AspectJ记录日志
- 第一次使用struts2问题记录
- 第一次使用debian运行django记录
- 记录第一次使用jni编译so包的入门操作
- 第一次使用linux并编写了一个dump mysql的程序,记录下简单的步骤
- 记录第一次使用android studio签名打包
- 第一次使用aspnet_compiler失败记录
- 第一次使用博客记录学习生活------2017.7.9
- 第一次使用csdn的博客,记录一个小产品的开发过程
- 第一次使用less记录
- 使用git第一次成功,记录
- Android开发中使用SharedPreferences记录用户是否第一次启动程序
- 记录:第一次使用ajax
- 第一次使用css样式啊,先记录一下先
- Android开发中使用SharedPreferences记录用户是否第一次启动程序
- 第一次使用博客心情记录
- 第一次使用MongoDB 插入记录遇到的问题
- 第一次使用博客,先记录一下吧
- 第一次使用这种样式的网页。感觉很好玩啊。
- 使用GridView添加,删除,编辑记录