自定义Spring的Aop切面类拦截业务请求,并获取到请求的参数名和参数值

2022-06-25 09:57:58

在切面类中如何获取请求的参数,和参数对应的值?

Object[] args = joinPoint.getArgs();(import org.aspectj.lang.JoinPoint;)

只能获取参数值而不能连同参数名一起获取。

测试结果:

后台获取:

需要引入javassist的jar包

<dependency>
    <groupId>javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.3</version>
</dependency>
package com.whoareyou.fido.rest.aop;

import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;

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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.whoareyou.fido.rest.util.LogAopUtil;

/**
 * 使用AOP进行日志记录
 * com.whoareyou.fido.rest.controller包及子包下所有类所有public方法都被添加此AOP进行日志记录
 * 
 * @author shengquan
 */
@Aspect
// 声明是个spring管理的bean
@Component
@Order(1)
public class LogAop {
	private static final Logger log = LoggerFactory.getLogger(LogAop.class);

	// 声明一个切点 里面是 execution表达式
	@Pointcut("execution(public * com.whoareyou.fido.rest.controller..*.*(..))")
	private void controllerAspect() {
	}

	// 请求method前打印内容
	@Before(value = "controllerAspect()")
	public void methodBefore(JoinPoint joinPoint) throws Exception {
		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
				.getRequestAttributes();
		HttpServletRequest request = requestAttributes.getRequest();
		// 打印请求内容
		log.info("===============请求内容===============");
		log.info("请求地址:" + request.getRequestURL().toString());
		log.info("请求方式:" + request.getMethod());
		log.info("请求类方法:" + joinPoint.getSignature());
		log.info("请求类方法参数:" + Arrays.toString(joinPoint.getArgs()));

		Object[] args = joinPoint.getArgs();
		String classType = joinPoint.getTarget().getClass().getName();
		Class<?> clazz = Class.forName(classType);
		String clazzName = clazz.getName();
		String methodName = joinPoint.getSignature().getName(); // 获取方法名称
		// 获取参数名称和值
		StringBuffer sb = LogAopUtil.getNameAndArgs(this.getClass(), clazzName, methodName, args);
		log.info("请求类方法参数名称和值:" + sb);
		log.info("===============请求内容===============");
	}

	// 在方法执行完结后打印返回内容
	@AfterReturning(returning = "o", pointcut = "controllerAspect()")
	public void methodAfterReturing(Object o) {
		log.info("--------------返回内容----------------");
		log.info("Response内容:" + JSON.toJSONString(o));
		log.info("--------------返回内容----------------");
	}
}

工具类:

package com.whoareyou.fido.rest.util;

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

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

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;

/**
 * 获取AOP代理的方法的参数名称和参数值工具类
 * 
 * @author shengquan
 */
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++) {
			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;
	}
}

Controller:

@RequestMapping("/testLogAop")
@ResponseBody
public Object testLogAop(Integer id, String name) {
		
    return testUserService.query();//这里随便
}
@RequestMapping("/testLogAop2")
@ResponseBody // 用实体类接收参数
public Object testLogAop2(TestUser user) {
    System.out.println("user.getName():" + user.getName());
    return testUserService.query();//这里随便
}
  • 作者:绳全
  • 原文链接:https://blog.csdn.net/weixin_41633157/article/details/79930992
    更新时间:2022-06-25 09:57:58