从ProceedingJoinPoint中检索参数值

Sha*_* PC 9 aop spring-aop spring-aspects

在我的请求中,我有一个参数名称"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 ?
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

通话方式:

public MyResponse saveUser(
    @RequestParam("accessToken") String accessToken,
    @RequestBody final UserDto userDto
) {
    // code 
}
Run Code Online (Sandbox Code Playgroud)

我想在AOP中获取此访问令牌.

提前致谢.

kri*_*aex 23

好吧,Shamseer,我只是有一点闲暇时间,所以我试图回答你的问题而不回答我的评论中的所有问题.我这样做的方法是我不会使用参数名称,但尝试将参数与注释@RequestParam("accessToken")匹配,即我将在注释类型和值上匹配魔术名称"accessToken"而不是方法参数名称由于在编译期间从类文件中剥离调试信息或由于混淆而从不知道您的方面的人进行简单的重构,可能会改变.

这是一些自我一致的示例代码,它是针对AspectJ而不是Spring AOP进行测试的,但后者的语法无论如何都是前者语法的一个子集:

使用main方法的示例类:

有三种方法,所有方法都对其中一个@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

虚拟助手类使代码编译:

package de.scrum_master.app;

public class UserDto {}
Run Code Online (Sandbox Code Playgroud)

方面:

请注意,我的全部切入点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();
    }
}
Run Code Online (Sandbox Code Playgroud)

控制台输出:

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
Run Code Online (Sandbox Code Playgroud)

有关类似代码的相关但有点简单的问题,请参阅此答案.


SMA*_*SMA 6

要获取作为方法参数的参数,可以尝试如下操作:

Object[] methodArguments = joinPoint.getArgs();
Run Code Online (Sandbox Code Playgroud)