AOP方式配置日志,打印uri、url、入参参数名、入参参数值、返回结果。

1、maven的pom配置,javassist和gson的jar依赖。



    com.google.code.gson
    gson
    2.6.2




    org.javassist
    javassist
    3.20.0-GA
2、java的aop配置代码:


package com.brilliance.avictc.wealth.filter;

import javassist.*;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

import java.lang.reflect.Method;

import com.google.gson.Gson;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @describe: 统一处理打印入参到日志
 * @date: 2020-10-15
 * @author: yxt
 */
@Component  //声明组件
@Aspect //  声明切面
@ComponentScan  //组件自动扫描
@EnableAspectJAutoProxy //spring自动切换JDK动态代理和CGLIB
public class LoggerByAop {

    /**
     *自定义日志
     */
    private Logger logger = LoggerFactory.getLogger(LoggerByAop.class);

    /**
     * Before : 在方法执行前进行切面
     * execution : 定义切面表达式,多个用||分隔
     * public * com.eparty.ccp.*.impl..*.*(..)
     * *  *..*.*.controller..*.*(..)
     * public :匹配所有目标类的public方法,不写则匹配所有访问权限
     * 第一个* :方法返回值类型,*代表所有类型
     * 第二个* :包路径的通配符
     * 第三个..* :表示impl这个目录下所有的类,包括子目录的类
     * 第四个*(..) : *表示所有任意方法名,..表示任意参数
     * @param point 切面
     */
    @Before("execution(public * com.brilliance.avictc.wealth.controller.*.*(..)) || execution(* com.brilliance.avictc.wealth.service.UAPApiService.*(..))||execution(public * com.brilliance.avictc.wealth.property.controller.*.*(..))")
    public void before(JoinPoint point) {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime",startTime);
        this.printMethodParams(point);
    }

    /**
     * 打印类method的名称以及参数
     * @param point 切面
     */
    public void printMethodParams(JoinPoint point){
        if(point == null){
            return;
        }
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        // long costTime = System.currentTimeMillis() - (long) request.getAttribute("startTime");
        //String url = request.getRequestURL().toString();
        String uri = request.getRequestURI();
        // logger.info("uri为:{}___{},————————总耗时:{}",uri,endTime-startTime);
         // Signature 包含了方法名、申明类型以及地址等信息
        String class_name = point.getTarget().getClass().getName();
        String method_name = point.getSignature().getName();
        //重新定义日志
        logger = LoggerFactory.getLogger(point.getTarget().getClass());
         // 获取方法的参数值数组。
        Object[] method_args = point.getArgs();
        try {
             // 获取方法参数名称
            Map paramMap = new HashMap<>();
            Mapmaps =  request.getParameterMap();
            if(maps != null){
                for (Map.Entry entry : maps.entrySet()) {
                    paramMap.put(entry.getKey(),Arrays.toString(entry.getValue()));
//                param = entry.getKey() + ":"+Arrays.toString(entry.getValue())+";";
                }
            }
            String param = paramMap.toString();
            //String[] paramNames = getFieldsName(class_name, method_name);
            String[] paramNamesCrm = getFieldsName(class_name, method_name);
             // 打印方法的参数名和参数值
            String paramCrm = logParam(paramNamesCrm, method_args);
            if("com.brilliance.avictc.wealth.service.UAPApiService".equals(class_name)){
                logger.info("..... 调用crm接口入参信息 .....:uri:{},{}.{}:{}" , uri, class_name, method_name, paramCrm);
            }else{
                logger.info("***** 客户端接口入参信息 *****:uri:{},{}.{}:{}",uri, class_name, method_name, param);
            }

        } catch (Exception e) {
            logger.error("切面获取入参的参数名和参数值时,发生异常,异常信息为:"+e);
        }
    }

    /**
     * 使用javassist来获取方法参数名称
     * @param class_name    类名
     * @param method_name   方法名
     * @return
     * @throws Exception
     */
    private String[] getFieldsName(String class_name, String method_name) throws Exception {
        Class clazz = Class.forName(class_name);
        String clazz_name = clazz.getName();
        ClassPool pool = ClassPool.getDefault();
        ClassClassPath classPath = new ClassClassPath(clazz);
        pool.insertClassPath(classPath);

        CtClass ctClass = pool.get(clazz_name);
        CtMethod ctMethod = ctClass.getDeclaredMethod(method_name);
        MethodInfo methodInfo = ctMethod.getMethodInfo();
        CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
        LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
        if(attr == null){
            return null;
        }
        String[] paramsArgsName = new String[ctMethod.getParameterTypes().length];
        int pos = Modifier.isStatic(ctMethod.getModifiers()) ? 0 : 1;
        for (int i=0;i clazz){
        if (clazz.isPrimitive() || clazz == String.class){
            return true;
        }else {
            return false;
        }
    }


    /**
     * 打印方法参数值  基本类型直接打印,非基本类型需要重写toString方法
     * @param paramsArgsName    方法参数名数组
     * @param paramsArgsValue   方法参数值数组
     */
    private String logParam(String[] paramsArgsName,Object[] paramsArgsValue){
        String resultStr = "";
        if(ArrayUtils.isEmpty(paramsArgsName) || ArrayUtils.isEmpty(paramsArgsValue)){
            logger.info("该方法没有参数");
            return resultStr;
        }
        // StringBuffer buffer = new StringBuffer();
        Map argsMap = new HashMap<>();
        for (int i=0;i

 

你可能感兴趣的:(Java,aop)