package com.jt.common.aspect;import java.lang.reflect.Method;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.stereotype.Service;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import com.jt.common.annotation.RequiredLog;import com.jt.common.util.IPUtils;import com.jt.common.util.ShiroUtils;import com.jt.sys.entity.SysLog;/*** * 借助@Aspect注解描述此类为一个切面对象, * 我们要在此类中实现日志记录操作.例如 * 用户添加,修改等业务操作执行我们要进行 * 日志记录. */@Aspect@Servicepublic class SysLogAspect { /** * 切入点的定义(借助@Pointcut注解进行描述) */ @Pointcut("bean(sysUserServiceImpl)") public void doPointCut(){} /** * @Around 修饰的的方法为一个环绕通知 * 可以在目标方法执行之前和之后添加扩展业务 * @param jp 连接点(封装了要执行的具体方法对象信息) * @return */ @Around("doPointCut()") //@Around("bean(sysUserServiceImpl)") public Object aroundMethod(ProceedingJoinPoint jp) throws Throwable{ //1.添加扩展功能 long startTime=System.currentTimeMillis(); //System.out.println("method.start:"+startTime); //2.执行目标方法(可以基于业务不执行目标方法) //result为目标方法的返回值 //System.out.println("invoke target method"); Object result=jp.proceed();//通过反射机制调用目标方法 //3.添加扩展功能 long endTime=System.currentTimeMillis(); //System.out.println("method.end:"+endTime); saveObject(jp,endTime-startTime); return result; } /**将用户行为日志存储到数据库中 * @throws JsonProcessingException * @throws SecurityException * @throws NoSuchMethodException */ private void saveObject(ProceedingJoinPoint jp,long time) throws JsonProcessingException, NoSuchMethodException, SecurityException { //1.获取要记录的用户行为数据 //1.1获取ip地址 String ip=IPUtils.getIpAddr(); //1.2获取登录用户名 String username=ShiroUtils.getPrincipal().getUsername(); //1.3获取用户操作 System.out.println(jp.getSignature().getClass().getName()); //1.3.1获取目标方法对象(先获取目标类,再获取目标方法对象) Class targetCls=jp.getTarget().getClass(); Method targetMethod = getTargetMethod(targetCls,jp); //1.3.2获取目标方法对象上的注解 RequiredLog rLog= targetMethod.getDeclaredAnnotation(RequiredLog.class); //1.3.3获取注解中定义的操作名 String operation=rLog!=null?rLog.operation():"unkown"; //1.4 获取方法名 String method=targetCls.getSimpleName()+"."+targetMethod.getName(); String params=new ObjectMapper()//jackson .writeValueAsString(jp.getArgs()); //2.封装用户行为数据 SysLog log=new SysLog(); log.setIp(ip); log.setUsername(username); log.setOperation(operation); log.setMethod(method); log.setParams(params); log.setTime(time); //log.setCreateDate(createdTime); //3.将用户行为数据写入到数据库 //sysLogDao.insertObject(log); } //快速提取方法快捷键:alt+shift+m private Method getTargetMethod(Class targetCls,ProceedingJoinPoint jp) throws NoSuchMethodException { //获取方法签名对象 MethodSignature ms= (MethodSignature)jp.getSignature(); //ms.getMethod();接口方法对象 //获取方法参数类型 Class [] paramTypes=ms.getMethod().getParameterTypes(); //获取目标方法(先获取目标对象,再获取目标方法) Method targetMethod= targetCls.getDeclaredMethod( ms.getName(),paramTypes); return targetMethod; }}
切面开发: 借助@Aspect注解描述此类为一个切面对象,获取用户行为日志并且存储到数据库中