private void saveLog(ProceedingJoinPoint jp,long time)throws Throwable {
package com.cy.pj.common.aspect;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.cy.pj.common.annotation.RequiredLog;
import com.cy.pj.common.util.IPUtils;
import com.cy.pj.sys.entity.SysLog;
import com.cy.pj.sys.service.SysLogService;
import lombok.extern.slf4j.Slf4j;
/**
* @Aspect 描述的類為切面類,此類中實現:
* 1)切入點(Pointcut)的定義
* 2)通知(advice)的定義(擴展功能)
*/
@Slf4j
@Aspect
@Component
public class SysLogAspect {
/**
* @Pointcut 注解用於描述或定義一個切入點
* 切入點的定義需要遵循spring中指定的表達式規范
例如:("bean(sysMenuServiceImpl)")為切入點表達式
的一種定義方式。
*/
//bean(bean名稱或一個表達式)
//@Pointcut("bean(sysMenuServiceImpl)")
@Pointcut("@annotation(com.cy.pj.common.annotation.RequiredLog)")
public void logPointCut() {}
/**
* @Around 注解描述的方法為一個環繞通知方法,
* 在此方法中可以添加擴展業務邏輯,可以調用下一個
切面對象或目標方法
* @param jp 連接點(此連接點只應用@Around描述的方法)
* @return
* @throws Throwable
*/
@Around("logPointCut()")
public Object aroundAdvice(ProceedingJoinPoint jp)
throws Throwable{
long start=System.currentTimeMillis();
log.info("start:"+start);
Object result=jp.proceed();//調用下一個切面或目標方法
long end=System.currentTimeMillis();
log.info("end:"+end);
//記錄日志(用戶行為信息)
saveLog(jp,(end-start));
return result;
}
@Autowired
private SysLogService sysLogService;
//日志記錄
private void saveLog(ProceedingJoinPoint jp,long time)throws Throwable {
//1.獲取用戶行為日志(ip,username,operation,method,params,time,createdTime)
//獲取類的字節碼對象,通過字節碼對象獲取方法信息
Class<?> targetCls=jp.getTarget().getClass();
//獲取方法簽名(通過此簽名獲取目標方法信息)
MethodSignature ms=(MethodSignature)jp.getSignature();
//獲取目標方法上的注解指定的操作名稱
Method targetMethod=
targetCls.getDeclaredMethod(
ms.getName(),
ms.getParameterTypes());
RequiredLog requiredLog=
targetMethod.getAnnotation(RequiredLog.class);
String operation=requiredLog.value();
System.out.println("targetMethod="+targetMethod);
//獲取目標方法名(目標類型+方法名)
String targetClsName=targetCls.getName();
String targetObjectMethodName=targetClsName+"."+ms.getName();
//獲取請求參數
String targetMethodParams=Arrays.toString(jp.getArgs());
//2.封裝用戶行為日志(SysLog)
SysLog entity=new SysLog();
entity.setIp(IPUtils.getIpAddr());
entity.setUsername("admin");
entity.setOperation(operation);
entity.setMethod(targetObjectMethodName);
entity.setParams(targetMethodParams);
entity.setTime(time);
entity.setCreatedTime(new Date());
//3.調用業務層對象方法(saveObject)將日志寫入到數據庫
sysLogService.saveObject(entity);
}
}
}
https://www.yuque.com/binarylei/java/annotation