当前位置: 代码迷 >> 综合 >> AOP方式配置日志,打印uri、url、入参参数名、入参参数值、返回结果。
  详细解决方案

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

热度:41   发布时间:2024-02-28 23:17:30.0
1、maven的pom配置,javassist和gson的jar依赖。
<!--GSON  add by yxt 2020.10.15 -->
<dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.6.2</version>
</dependency><!--javassist  add by yxt 2020.10.15 -->
<dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.20.0-GA</version>
</dependency>
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 {// 获取方法参数名称String[] paramNames = getFieldsName(class_name, method_name);// 打印方法的参数名和参数值String param = logParam(paramNames, method_args);if("com.brilliance.avictc.wealth.service.UAPApiService".equals(class_name)){logger.info("..... 调用crm接口入参信息 .....:uri:{},{}.{}:{}" , uri, class_name, method_name, param);}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<paramsArgsName.length;i++){paramsArgsName[i] = attr.variableName(i + pos);}return paramsArgsName;}/*** 判断是否为基本类型:包括String* @param clazz clazz* @return  true:是;     false:不是*/private boolean isPrimite(Class<?> 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<String, Object> argsMap = new HashMap<>();for (int i=0;i<paramsArgsName.length;i++){//参数名String name = paramsArgsName[i];//参数值Object value = paramsArgsValue[i];argsMap.put(name,value);// buffer.append(name +" = ");
//            if(isPrimite(value.getClass())){
//                buffer.append(value + "  ,");//            }else {
//                buffer.append(value.toString() + "  ,");
//            }}resultStr = argsMap.toString();return resultStr;}// 统一切点,对com.hangtian.admin.controller及其子包中所有的类的所有方法切面@Pointcut("execution(public * com.brilliance.avictc.wealth.controller.*.*(..)) || execution(* com.brilliance.avictc.wealth.service.UAPApiService.*(..))||execution(public * com.brilliance.avictc.wealth.property.controller.*.*(..))")public void Pointcut() {}@AfterReturning(value="Pointcut()",returning="rvt")public void after(JoinPoint joinPoint,Object rvt){MethodSignature sig1 = (MethodSignature)joinPoint.getSignature();Method method1 = sig1.getMethod();RequestAttributes ra = RequestContextHolder.getRequestAttributes();ServletRequestAttributes sra = (ServletRequestAttributes) ra;HttpServletRequest request = sra.getRequest();long costTime = System.currentTimeMillis() - (long) request.getAttribute("startTime");if(null != rvt && null != method1.getDeclaringClass()){try{if("com.brilliance.avictc.wealth.service.UAPApiService".equals(method1.getDeclaringClass().getName())){logger.info("----- 调用crm接口返回结果 -----:time:{},{}.{}:{}" ,costTime, method1.getDeclaringClass().getName(),method1.getName(),new Gson().toJson(rvt));}else{logger.info("===== 客户端返结果为 =====:time:{},{}.{} :{}",costTime, method1.getDeclaringClass().getName(),method1.getName(),new Gson().toJson(rvt));}}catch (Exception e){logger.error("切面获取返回值时,发生异常,异常信息为:"+e);}}}
}

 

  相关解决方案