@Aspect LogAdvice ssm日志输出代码:

架构ssm

用到jar :javassist.jar 反序列化操作

直接上代码输出:

 

package com.liangq.common.advice;

import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.google.gson.Gson;
import com.liangq.common.util.Const;
import com.liangq.common.util.LogAopUtil;
import com.liangq.common.util.LogUtil;
import com.liangq.common.util.StringUtil;
import com.liangq.common.util.UUIDUtil;

import cn.hutool.core.util.URLUtil;  

@Aspect
public class LogAdvice {
	
	  
    private String requestPath = null ; // 请求地址  
    private String userName = null ; // 用户名  
    private Map<String, Object> outputParamMap = null; // 存放输出结果  
    private long startTimeMillis = 0; // 开始时间  
    private long endTimeMillis = 0; // 结束时间 
    private String method =null;//请求方式
    private  String requestClassMethod =null;//请求方法
    private  String requestClassMethodName =null;//请求方法
  
    /** 
     * <p>Title: doBeforeInServiceLayer</p>  
     * <p>Description: 方法调用前触发 记录开始时间 </p>  
     * @param joinPoint
     */
    @Before("execution(public * com.liangq.*.controller..*.*(..))")  
    public void doBeforeInServiceLayer(JoinPoint joinPoint) {  
        startTimeMillis = System.currentTimeMillis(); // 记录方法开始执行的时间  
    }  
  
    /** 
     * <p>Title: doAfterInServiceLayer</p>  
     * <p>Description: 方法调用后触发 记录结束时间</p>  
     * @param joinPoint
     */
    @After("execution(public * com.liangq..*.controller..*.*(..))")  
    public void doAfterInServiceLayer(JoinPoint joinPoint) {  
        endTimeMillis = System.currentTimeMillis(); // 记录方法执行完成的时间  
        this.printOptLog();  
    }  
  
    /**
     * <p>Title: doAround</p>  
     * <p>Description: 环绕触发 </p>  
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("execution(public * com.liangq..*.controller..*.*(..))")  
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {  
        /** 
         * 1.获取request信息 
         * 2.根据request获取session 
         * 3.从session中取出登录用户信息 
         */  
    	HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        // 从session中获取用户信息 
		String loginInfo = StringUtil.getStringVlaue(request.getAttribute(Const.CURRENT_USER_ID));
        if(loginInfo != null && !"".equals(loginInfo)){  
            userName = loginInfo;  
        }else{  
            userName = "用户未登录" ;  
        }  
        
        String strClassName = pjp.getTarget().getClass().getName();
		String strMethodName = pjp.getSignature().getName();
        
		Object[] args = pjp.getArgs();
		String classType = pjp.getTarget().getClass().getName();
		Class<?> clazz = Class.forName(classType);
		String clazzName = clazz.getName();
		String methodName = pjp.getSignature().getName(); // 获取方法名称
		// 获取参数名称和值
		StringBuffer sb = LogAopUtil.getNameAndArgs(this.getClass(), clazzName, methodName, args);

		requestClassMethodName=sb.toString();
		
		requestClassMethod=strClassName+"."+strMethodName;
		

        // 获取请求地址  
        requestPath = request.getRequestURI();  
        // 获取方法
        method = request.getMethod();
          
        // 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行  
        outputParamMap = new HashMap<String, Object>();  
        Object result = pjp.proceed();// result的值就是被拦截方法的返回值  
        outputParamMap.put("result", result);  
          
        return result;  
    }  
  
    /** 
     * <p>Title: printOptLog</p>  
     * <p>Description: 输出日志 </p>
     */
    private void printOptLog() {  
    	String requestUuid = UUIDUtil.getUUID();
        Gson gson = new Gson(); // 需要用到google的gson解析包  
        String optTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startTimeMillis);  
        LogUtil.businessLog("===============用户["+userName+"]请求内容开始===============");
        LogUtil.businessLog("[" + requestUuid + "]"
        		+"\n  请求用户:"+userName  
        		+"\n  请求方式:"+method  
        		+"\n  请求方法:"+requestClassMethod  
        		+"\n  请求类方法参数名称和值:"+requestClassMethodName  
                +"\n  请求url:"+URLUtil.getPath(requestPath)+"; "
                +"\n  开始时间:" + optTime  
                +"\n  耗时:" + (endTimeMillis - startTimeMillis) + "ms ;"  
                +"\n  请求出参:"+gson.toJson(outputParamMap));  
        LogUtil.businessLog("===============用户["+userName+"]请求内容结束===============");
    }  
		
	
}

反序列类应用:

 

 

package com.liangq.common.util;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.Modifier;
import javassist.NotFoundException;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
 
/**
* <p>Title: LogAopUtil</p>  
* <p>Description: 获取AOP代理的方法的参数名称和参数值工具类</p>  
* @author liangq  
* @date 2020年4月17日
 */
public class LogAopUtil {
	public static StringBuffer getNameAndArgs(Class<?> cls, String clazzName, String methodName, Object[] args)
			throws NotFoundException {
 
        
		Map<String, Object> nameAndArgs = new HashMap<String, Object>();
 
		ClassPool pool = ClassPool.getDefault();
		ClassClassPath classPath = new ClassClassPath(cls);
		pool.insertClassPath(classPath);
 
		CtClass cc = pool.get(clazzName);
		CtMethod cm = cc.getDeclaredMethod(methodName);
		MethodInfo methodInfo = cm.getMethodInfo();
		CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
		LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
		if (attr == null) {
			// exception
		}
		int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
		for (int i = 0; i < cm.getParameterTypes().length; i++) {
			//过滤掉Request或者Response对象
			if ((!(args[i] instanceof HttpServletRequest) && !(args[i] instanceof HttpServletResponse))) {
				nameAndArgs.put(attr.variableName(i + pos), args[i]);// paramNames即参数名
			}
		}
 
		// nameAndArgs的两种类型,用实体类接收的类似这样:
		// reqParams=com.whoareyou.fido.rest.User@616b9c0e
		// 用Map<String,Object>接收的是这样:menuNo=56473283,遍历这个map区分两种不同,使用不同的取值方式。
		// 根据获取到的值所属的不同类型通过两种不同的方法获取参数
		boolean flag = false;
		if (nameAndArgs != null && nameAndArgs.size() > 0) {
			for (Map.Entry<String, Object> entry : nameAndArgs.entrySet()) {
				if (entry.getValue() instanceof String) {
					flag = true;
					break;
				}
			}
		}
		StringBuffer sb = new StringBuffer();
		if (flag) {
			// 从Map中获取
			sb.append(JSON.toJSONString(nameAndArgs));
		} else {
			if (args != null) {
				for (Object object : args) {
					if (object != null) {
						if (object instanceof MultipartFile || object instanceof ServletRequest
								|| object instanceof ServletResponse) {
							continue;
						}
						sb.append(JSON.toJSONString(object));
					}
				}
			}
		}
		return sb;
	}
}

 

 

输出内容:

[2020-04-20 21:12:14] [businessLog-INFO 39] ===============用户[用户名]请求内容开始===============
[2020-04-20 21:12:14] [businessLog-INFO 39] [647d39d049104a14bcbe33172016db28]
  请求用户:
  请求方式:POST
  请求方法:
  请求类方法参数名称和值:110
  请求url:
  开始时间:2020-04-20 21:12:14
  耗时:
  请求出参:
[2020-04-20 21:12:14] [businessLog-INFO 39] ===============用户[用户名]请求内容结束===============

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值