在我的请求中,我有一个参数名称“ accessToken”,如何从ProceedingJoinPoint中获取请求参数值?
public Object handleAccessToken(ProceedingJoinPoint joinPoint) throws Throwable {
final Signature signature = joinPoint.getStaticPart().getSignature();
if (signature instanceof MethodSignature) {
final MethodSignature ms = (MethodSignature) signature;
String[] params = ms.getParameterNames();
for (String param : params) {
System.out.println(param);
// here how do i get parameter value using param ?
}
}
}
调用方法:
public MyResponse saveUser(
@RequestParam("accessToken") String accessToken,
@RequestBody final UserDto userDto
) {
// code
}
我想在AOP中获得此访问令牌。
提前感谢。
[好,Shamseer,我只有一点空闲时间,所以我试图回答您的问题,而不让您回答我的所有评论。我这样做的方法是,我将not使用参数名称,但是尝试在带有注释@RequestParam("accessToken")
的参数上进行匹配,即,我将在注释类型和值上使用魔术名称进行匹配“ accessToken”的名称,而不是方法参数名称,该名称可能会由于不知道您的方面的人的简单重构,由于在编译过程中从类文件中删除调试信息或混淆而可能改变。
这里有一些自洽的示例代码,它们是针对AspectJ而不是Spring AOP进行测试的,但是后者的语法还是前者语法的子集:
带有主方法的示例类:
[共有三种方法,所有这些方法都在其中一个参数上带有@RequestParam
批注,但是其中只有两个具有魔术值“ accessToken”。无论参数类型如何(一个String
和一个int
),它们都应该匹配,但是不匹配@RequestParam("someParameter")
的参数。严格来说,所有方法执行都是匹配的,但是运行时反射消除了不需要的执行。如果您的注释位于类或方法级别或参数类型上,我们可以在切入点中将它们直接匹配而无需反射,但是在参数注释的情况下,这超出了AspectJ的当前(v1.8.4)功能,我们必须使用反射,很不幸。
package de.scrum_master.app;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
public class MyResponse {
public MyResponse saveUser(
@RequestParam("accessToken") String accessToken,
@RequestBody final UserDto userDto
) {
return this;
}
public MyResponse doSomething(
@RequestParam("someParameter") String text,
@RequestBody final UserDto userDto
) {
return this;
}
public MyResponse doSomethingElse(
@RequestParam("accessToken") int number
) {
return this;
}
public static void main(String[] args) {
MyResponse myResponse = new MyResponse();
myResponse.doSomething("I am not a token", new UserDto());
myResponse.saveUser("I am a token", new UserDto());
myResponse.doSomethingElse(12345);
}
}
虚拟助手类,使代码编译:
package de.scrum_master.app;
public class UserDto {}
方面:
[请注意,我的综合切入点execution(* *(..))
仅用于说明。您应该将其范围缩小到实际需要的方法。
package de.scrum_master.aspect;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.bind.annotation.RequestParam;
@Aspect
public class AccessTokenAspect {
@Around("execution(* *(..))")
public Object handleAccessToken(ProceedingJoinPoint thisJoinPoint) throws Throwable {
System.out.println(thisJoinPoint);
Object[] args = thisJoinPoint.getArgs();
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getStaticPart().getSignature();
Method method = methodSignature.getMethod();
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
assert args.length == parameterAnnotations.length;
for (int argIndex = 0; argIndex < args.length; argIndex++) {
for (Annotation annotation : parameterAnnotations[argIndex]) {
if (!(annotation instanceof RequestParam))
continue;
RequestParam requestParam = (RequestParam) annotation;
if (! "accessToken".equals(requestParam.value()))
continue;
System.out.println(" " + requestParam.value() + " = " + args[argIndex]);
}
}
return thisJoinPoint.proceed();
}
}
控制台输出:
execution(void de.scrum_master.app.MyResponse.main(String[]))
execution(MyResponse de.scrum_master.app.MyResponse.doSomething(String, UserDto))
execution(MyResponse de.scrum_master.app.MyResponse.saveUser(String, UserDto))
accessToken = I am a token
execution(MyResponse de.scrum_master.app.MyResponse.doSomethingElse(int))
accessToken = 12345
另请参见this answer有关一个相似但代码简单的问题。
要获取作为方法参数的参数,可以尝试以下操作:
Object[] methodArguments = joinPoint.getArgs();
如果使用@Aspect,则可以在Aspect中添加此方法,并发送JoinPoint和所需参数的名称。
private Object getParameter(ProceedingJoinPoint joinPoint, String parameterName) {
Object valueParameter = null;
if (Objects.nonNull(joinPoint) && joinPoint.getSignature() instanceof MethodSignature
&& Objects.nonNull(parameterName) ) {
MethodSignature method = (MethodSignature)joinPoint.getSignature();
String[] parameters = method.getParameterNames();
for (int t = 0; t< parameters.length; t++) {
if( Objects.nonNull(parameters[t]) && parameters[t].equals(parameterName)) {
Object[] obj = joinPoint.getArgs();
valueParameter = obj[t];
}
}
}
return valueParameter;
}
以及通话示例:
Object parameterObject = getParameter(joinPoint, "nameClient");
if ( Objects.nonNull(parameterObject) ) {
String parametro = String.valueOf(parameterObject);
}
只需要知道要转换的对象的类型