JAVA 自定义注解+AOP

目录

一、创建自定义注解

二、创建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实现记录日志功能

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值