aop实现打印相关日志信息

这里会去截取请求中的参数

主要作用: 获取一次请求的访问ip, url, 分支机构, 方法名, 关键字, 访问时间, 请求唯一标识, 参数等, 然后统一打印出来, 方便查看日志排查问题
主要实现: 通过反射的方式将请求中的参数的值获取到.(一种是参数为一个对象的情况, 另一种是参数为多个单独参数的情况, 都进行了分别的处理)

 

package xxx;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Component
@Aspect
@Slf4j
public class LogAop {

//    @Value("${logParamKeywords}")
    private final String logParamKeywords = "registNo,taskId,businessId";

    @Before(value = "execution(* xxx..*Api.*(..))")
    public void beforeMethod(JoinPoint pjp){
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String methodName = pjp.getSignature().getName();
        Object[] args = pjp.getArgs();
        String []keywords = logParamKeywords == null? null : logParamKeywords.split(",");
        Map<String, String> fieldMap = new HashMap<>();
        String k = "";
        String v = "";
        String param;
        try {
            if (args != null) {
                if (args.length == 1 && !this.isBaseType(args[0].getClass())) {
                    fieldMap = getfieldsValue(args[0], keywords);
                    param = JSON.toJSONString(args[0]);
                } else {
                    Map<String, Object> paramMap = this.getParamValue(pjp);
                    param = JSON.toJSONString(paramMap);
                    if (keywords != null && paramMap != null && !paramMap.isEmpty()) {
                        for (String keyword : keywords) {
                            if (paramMap.get(keyword) != null) {
                                fieldMap.put(keyword, String.valueOf(paramMap.get(keyword)));
                                break;
                            }
                        }
                    }
                }
            } else {
                param = "参数为空!";
            }
            if (fieldMap != null && !fieldMap.isEmpty()) {
                k = String.valueOf(fieldMap.keySet().toArray()[0]);
                v = fieldMap.get(k);
            }
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes != null ? attributes.getRequest() : null;
            String ip = "request为空";
            String url = "request为空";
            String comCode = "request为空";
            if (request != null) {
                ip = request.getRemoteAddr();
                url = request.getRequestURL().toString();
                comCode = request.getHeader("comCode");
            }
            log.info("\n===============================================================================================================\n" +
                    "=====================API访问请求信息:=============================================================================\n" +
                    "=====================ip: "+ip+"\n" +
                    "=====================url: "+url+"\n" +
                    "=====================sharding_comCode: "+comCode+"\n" +
                    "=====================方法名: "+methodName+"\n" +
                    "=====================关键字: "+k+"["+v+"]\n" +
                    "=====================时间: "+df.format(new Date())+"\n" +
                    "=====================参数: "+param+"\n" +
                    "===============================================================================================================\n" +
                    "===============================================================================================================");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param obj
     * @param keywords
     */
    private Map<String, String> getfieldsValue(Object obj, String[] keywords) {
        if (keywords == null) {
            return null;
        }
        Map<String, String> fieldMap = new HashMap<>();
        List<Field> fields = this.getFields(obj);
        for (String field : keywords) {
            for (Field item : fields) {
                item.setAccessible(true);
                try {
                    // 字段名
                    if (item.getName().equals(field) && item.get(obj) != null) {
                        //赋值
                        fieldMap.put(field, String.valueOf(item.get(obj)));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (!fieldMap.isEmpty()) {
                return fieldMap;
            }
        }
        return fieldMap;
    }

    /**
     * 判断是否是基本数据类型以及常用数据类型
     * @param className
     * @return
     */
    private boolean isBaseType(Class className) {
        return className.equals(Integer.class) ||
                className.equals(int.class) ||
                className.equals(Byte.class) ||
                className.equals(byte.class) ||
                className.equals(Long.class) ||
                className.equals(long.class) ||
                className.equals(Double.class) ||
                className.equals(double.class) ||
                className.equals(Float.class) ||
                className.equals(float.class) ||
                className.equals(Character.class) ||
                className.equals(char.class) ||
                className.equals(Short.class) ||
                className.equals(short.class) ||
                className.equals(Boolean.class) ||
                className.equals(boolean.class) ||
                className.equals(BigDecimal.class) ||
                className.equals(String.class);
    }

    /**
     * 返回该类及其父类的所有声明的字段,即包括public、private和proteced修饰的字段, 排除了Object父类
     * @param obj
     * @return
     */
    private List<Field> getFields(Object obj) {
        Class<?> tempClass = obj.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (tempClass != null && !"java.lang.object".equalsIgnoreCase(tempClass.getName())) {
            fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));
            tempClass = tempClass.getSuperclass();
        }
        return fieldList;
    }

    /**
     * 传入参数为多个单独参数的时候, 取各个参数值及结果到map中
     * @param pjp
     * @return
     */
    private Map<String, Object> getParamValue(JoinPoint pjp) {
        Object[] args = pjp.getArgs();
        String classType = pjp.getTarget().getClass().getName();
        String methodName = pjp.getSignature().getName();
        Map<String, Object> paramMap = new LinkedHashMap<>(2);
        try {
            // 参数值
            Class<?>[] classes = new Class[args.length];
            boolean noClassesFlag = false;
            for (int k = 0; k < args.length; k++) {
                if (args[k] instanceof MultipartFile || args[k] instanceof ServletRequest || args[k] instanceof ServletResponse) {
                    return paramMap;
                }
                if (args[k] == null) {
                    noClassesFlag = true;
                    break;
                }
                if (!args[k].getClass().isPrimitive()) {
                    // 当方法参数是封装类型
                    Class s = args[k].getClass();
                    classes[k] = s == null ? args[k].getClass() : s;
                }
            }
            ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
            // 获取指定的方法
            Method method = null;
            if (noClassesFlag) {
                Method[] methods = Class.forName(classType).getDeclaredMethods();
                for (Method ms : methods) {
                    String name = ms.getName();
                    Class<?>[] paramTypes = ms.getParameterTypes();
                    if (methodName.equals(name) && classes.length == paramTypes.length) {
                        method = Class.forName(classType).getMethod(methodName, paramTypes);
                    }
                }
                if (method == null) {
                    return paramMap;
                }
            } else {
                method = Class.forName(classType).getMethod(methodName, classes);
            }

            // 参数名
            String[] parameterNames = pnd.getParameterNames(method);
            // 通过map封装参数和参数值
            if (parameterNames != null) {
                for (int i = 0; i < parameterNames.length; i++) {
                    paramMap.put(parameterNames[i], args[i]);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return paramMap;
    }
}

 

posted @ 2021-09-22 15:11  双子家的咸蛋蛋  阅读(44)  评论(0编辑  收藏  举报