您的位置:首页 > 编程语言 > ASP

第一次使用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

//@Component

public class SysOpeLogAspect {

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



@Autowired

private 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 e

try {

//获得注解

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] 


三、注意点


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

                需要注意的是在applicationContext中配置如下代码,那么设置将无法生效。参考资料:http://bbs.csdn.net/topics/391049202?page=1

                

<!-- 启用aop -->

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

<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的自定义注解

                参考:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html

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


          4.spring的execution表达式

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

http://blog.csdn.net/peng658890/article/details/7223046


          5.在切面中获取request

                    参考:http://www.cnblogs.com/softidea/p/5904833.html

                     代码片段如下:

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的拦截器及切面

功能很强大,但是使用到的机会却不多。需要自己多多实践
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息