在切面类中如何获取请求的参数,和参数对应的值?
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();//这里随便
}