1、注解类
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD}) //应用于方法上面
@Retention(RetentionPolicy.RUNTIME)//表示在运行时注解任可用
public @interface OperationLogAnno {
/**
* 操作位置
*/
String operatePage() default "";
/**
* 操作类型
*/
String operateType() default "";
/**
* 业务域,各自业务自己定义
*/
String bizType() default "";
}
2、pom 引入面向切面依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
3、切面类切到注解上
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.example.annotation.OperationLogAnno;
import org.springframework.stereotype.Component;
import org.springframework.util.PatternMatchUtils;
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.Method;
import java.util.HashMap;
import java.util.Map;
@Aspect
@Component
@Slf4j
public class LogAspect {
private static final ThreadLocal<String> threadLocal=new ThreadLocal<>();
//切点
@Pointcut("@annotation(org.example.annotation.OperationLogAnno)")
private void cutMethod() {
}
//
@Before("cutMethod()")
public void before(JoinPoint joinPoint) throws Throwable {
String uuid = IdUtil.simpleUUID();
log.info("uuid:"+uuid);
threadLocal.set(uuid);
// 获取方法名
String methodName = joinPoint.getSignature().getName();
log.info("methodName={}", methodName);
// 反射获取目标类
Class<?> targetClass = joinPoint.getTarget().getClass();
Object[] params = joinPoint.getArgs();
log.info("params={}", params);
// 拿到方法对应的参数类型
Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
// 根据类、方法、参数类型(重载)获取到方法的具体信息
Method objMethod = targetClass.getMethod(methodName, parameterTypes);
// 获取方法上声明的注解
OperationLogAnno anno = objMethod.getDeclaredAnnotation(OperationLogAnno.class);
if( anno== null ){
//尝试获取接口上的注解类
anno = (OperationLogAnno) ((Class) AopUtils.getTargetClass(joinPoint.getTarget()).getGenericInterfaces()[0]).getDeclaredMethod(objMethod.getName(),parameterTypes).getAnnotation(OperationLogAnno.class);
}
info(anno);
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String servletPath = request.getServletPath();
log.info("servletPath:" + servletPath);
log.info("路径匹配结果" + PatternMatchUtils.simpleMatch("/user/**", servletPath));
//url
log.info("url={}", request.getRequestURL());
//method
log.info("method={}", request.getMethod());
//ip
log.info("ip={}", request.getRemoteAddr());
//类方法
log.info("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
Object[] r = joinPoint.getArgs();
//参数
log.info("args={}", r);
}
@After(value = "cutMethod()")
public void after() {
log.info("after.........");
log.info("uuid:"+threadLocal.get());
}
@AfterReturning(returning = "object", pointcut = "cutMethod()")
public void doAfterReturning(Object object) {
log.info("response={}", JSONUtil.toJsonStr(object));
}
@AfterThrowing(value="cutMethod()",throwing = "exception")
public void afterThrowing(Exception exception) {
System.out.println("afterThrowing.........");
log.info("exception:",exception);
}
@Around(value = "cutMethod()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("doAroundFront");
Object res = null;
try {
res = joinPoint.proceed(joinPoint.getArgs());
} catch (Throwable e) {
log.error("切面异常",e);
throw e;
}
//对res修改可以更改返回值
System.out.println("doAroundBehind");
return res;
}
@SneakyThrows
private <T extends Annotation>void info(T t) {
Method[] methods=t.getClass().getDeclaredMethods();
Map<String,String> map=new HashMap<>();
for(Method method:methods){
if(!method.getName().contains("hashCode")&&
!method.getName().contains("equals")&&
!method.getName().contains("toString")&&
!method.getName().contains("annotationType")){
map.put(method.getName(),(String)method.invoke(t));
}
}
log.info("annotation={}", map);
}
}