目录
一、创建自定义注解
二、创建aop类
三、实现实例
一、创建自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义注解类
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotate {
String value() default "";
}
二、创建aop类
import com.alibaba.fastjson.JSON;
import com.demo.util.HttpContextUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* 自定义aop
*/
@Aspect
@Slf4j
@Component
public class CustomAspect {
//定义切点
@Pointcut(value="@annotation(com.demo.annotate.CustomAnnotate)")
public void pointcut() { }
//定义切点
@Pointcut(value="execution(* com.demo.controller.*.*(..))")
public void operErrorPointCut() { }
/**
* 执行切点之前
*/
@Before(value = "@annotation(com.demo.annotate.CustomAnnotate)")
public void doBefore(JoinPoint joinPoint) {
log.info("=====================开始执行前置通知==================");
try {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class<?> targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String operation = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class<?>[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
operation = method.getAnnotation(CustomAnnotate.class).value();// 内容
break;
}
}
}
StringBuilder paramsBuf = new StringBuilder();
for (Object arg : arguments) {
paramsBuf.append(arg);
paramsBuf.append("&");
}
// *========控制台输出=========*//
log.info("[X用户]执行了[" + operation + "],类:" + targetName + ",方法名:" + methodName + ",参数:"
+ paramsBuf.toString());
log.info("=====================执行前置通知结束==================");
} catch (Throwable e) {
log.info("around " + joinPoint + " with exception : " + e.getMessage());
}
}
/**
* 接口返回异常导致异常不能被抛出
*/
// @Around("pointcut()")
// public void around(ProceedingJoinPoint point) {
// log.info("=====================使用环绕通知==================");
// printLog(point);
// }
@After("pointcut()")
public void after(JoinPoint joinPoint) {
log.info("=====================开始执行后置通知==================");
try {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class<?> targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String operation = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class<?>[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
operation = method.getAnnotation(CustomAnnotate.class).value();// 操作人
break;
}
}
}
StringBuilder paramsBuf = new StringBuilder();
for (Object arg : arguments) {
paramsBuf.append(arg);
paramsBuf.append("&");
}
// *========控制台输出=========*//
log.info("[X用户]执行了[" + operation + "],类:" + targetName + ",方法名:" + methodName + ",参数:"
+ paramsBuf.toString());
log.info("=====================执行后置通知结束==================");
} catch (Throwable e) {
log.info("around " + joinPoint + " with exception : " + e.getMessage());
}
}
private void printLog(ProceedingJoinPoint joinPoint){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
CustomAnnotate annotation = (CustomAnnotate)method.getAnnotation(CustomAnnotate.class);
if (annotation != null) {
// 注解上的描述
log.info("==>注解的内容:{}",annotation.value());
}
// 请求的方法名
String className = joinPoint.getTarget().getClass().getName();
log.info("==>请求的类:{}",className);
String methodName = signature.getName();
log.info("==>请求的方法:{}",methodName);
// 请求的方法参数值
Object[] args = joinPoint.getArgs();
// 请求的方法参数名称
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paramNames = u.getParameterNames(method);
if (args != null && paramNames != null) {
StringBuffer params = new StringBuffer();
for (int i = 0; i < args.length; i++) {
params.append(" " + paramNames[i] + ": " + args[i]);
}
log.info("==>请求的参数名称:{}",params);
}
//获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
//从获取到的RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
// 设置IP地址
if (request != null) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("X-Forwarded-For");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
{
ip = request.getRemoteAddr();
}
log.info("==>请求的ip:{}","0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip);
log.info("==>请求的URL:{}", request.getRequestURL().toString());
}
}
/**
* 设置操作异常切入点,拦截用户的操作日志,连接点正常执行后执行,若连接点抛出异常则不会执行
* @param joinPoint 切入点
* @param keys 返回结果
*/
@AfterReturning(value = "pointcut()", returning = "keys")
public void saveOperationLog(JoinPoint joinPoint, Object keys) {
log.info("=====================AfterReturning==================");
//获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
//从获取到的RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
try {
//在切面织入点通过反射机制获取织入点的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取织入点的方法
Method method = signature.getMethod();
//获取操作
CustomAnnotate annotation = method.getAnnotation(CustomAnnotate.class);
if (annotation != null) {
String value = annotation.value();
}
//获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
//获取请求的方法
String methodName = method.getName();;
methodName = className + "." + methodName;
log.info("==>请求的类:{},方法:{}",className,methodName);
Map<String, String> rtnMap = converMap(request.getParameterMap());
//将参数所在的数组转为json
String params = JSON.toJSONString(rtnMap);
log.info("==>请求的参数:{}",params);
log.info("==>请求的结果:{}",JSON.toJSONString(keys));
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 异常返回通知,用于拦截异常日志的信息,连接点抛出异常后执行
* @param joinPoint 切入点
* @param e 异常信息
*/
@AfterThrowing(pointcut = "operErrorPointCut()", throwing = "e")
public void saveErrorLog(JoinPoint joinPoint,Throwable e){
log.info("=====================AfterThrowing==================");
//获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
//从RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
try {
//在切面织入点通过反射机制获取织入点的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取织入点的方法
Method method = signature.getMethod();
//获取操作
CustomAnnotate annotation = method.getAnnotation(CustomAnnotate.class);
//获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
//获取请求的方法
String methodName = method.getName();
methodName = className + "." + methodName;
log.info("==>请求的类:{},方法:{}",className,methodName);
//请求的参数
Map<String, String> rtnMap = converMap(request.getParameterMap());
String params = JSON.toJSONString(rtnMap);
log.info("==>请求的参数:{}",params);
log.info("==>请求的异常名称:{}",e.getClass().getName());
log.info("==>请求的异常名称:{},异常内容:{}",e.getClass().getName(),e.getMessage());
//请求URI
log.info("==>请求URL:{}",request.getRequestURI());
}catch (Exception exception){
exception.printStackTrace();
}
}
/**
* 转换request请求参数
* @param paramMap request中获取的参数数组
* @return 转换后的数组
*/
public Map<String, String> converMap(Map<String,String[]> paramMap){
Map<String, String> rtnMap = new HashMap<>();
for (String key : paramMap.keySet()) {
rtnMap.put(key,paramMap.get(key)[0]);
}
return rtnMap;
}
}
三、实现实例
无异常接口
@RestController
@RequestMapping("/payment")
public class PaymentController {
@GetMapping("timeout")
@CustomAnnotate("测试")
public String timeout(){
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "payment success timeout";
}
}
有抛出异常接口
@RestController
@RequestMapping("/payment")
public class PaymentController {
@GetMapping("/index")
@CustomAnnotate("测试")
public String index(){
System.out.println("_____________________index_______________________");
throw new CommonException("exception.name.can.not.repeat","张三");
}
}
参考文献:
Aspect中execution和annotation使用及作用
AOP实现日志记录
springboot整合AOP实现记录日志功能