从 ProceedingJoinPoint 检索参数值 [英] Retrieve parameter value from ProceedingJoinPoint

查看:30
本文介绍了从 ProceedingJoinPoint 检索参数值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的请求中,我有一个参数名称accessToken",我如何从 ProceedingJoinPoint 获取请求参数值?

In my Request i have a parameter name "accessToken", how do i get request parameter value from 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 中获取这个访问令牌.

I want to get this access token in AOP.

提前致谢.

推荐答案

好吧,Shamseer,我只是有一点空闲时间,所以我试着回答你的问题,而你没有回答我评论中的所有问题.我这样做的方法是,我将使用参数名称,而是尝试使用注释来匹配参数@RequestParam("accessToken"),即我将在注释类型和值上使用accessToken"的魔法名称而不是方法参数名称进行匹配,该名称可能会由于不了解您的方面的人的简单重构而发生变化,因为从编译期间或由于混淆导致的类文件.

Okay, Shamseer, I just have a little sparetime, so I am trying to answer your question without you answering all my questions from my comments. The way I go about this is that I will not use parameter names, but try to match on parameters with an annotation @RequestParam("accessToken"), i.e. I will match on the annotation type and value with a magic name of "accessToken" rather than a method parameter name which might change due to a simple refactoring of someone who is unaware of your aspect, due to stripping debug information from the class file during compilation or due to obfuscation.

以下是一些针对 AspectJ 而非 Spring AOP 进行测试的自洽示例代码,但无论如何后者的语法是前者语法的一个子集:

Here is some self-consistent sample code which was tested against AspectJ, not Spring AOP, but the syntax of the latter is a subset of the former one's syntax anyway:

具有主要方法的示例类:

共有三种方法,所有方法在其中一个参数上都有一个@RequestParam 注释,但其中只有两个具有accessToken"的神奇值.无论参数类型如何(一个 String 和一个 int),它们都应该匹配,但是带有 @RequestParam("someParameter") 的应该匹配不匹配.严格来说,所有方法执行都是匹配的,但运行时反射消除了不需要的方法.如果您的注释是在类或方法级别或参数类型上,我们可以直接在切入点中匹配它们而无需反射,但在参数注释的情况下,这超出了 AspectJ 当前(v1.8.4)的能力,我们必须使用反射,不幸的是.

There are three methods, all of which have a @RequestParam annotation on one of the parameters, but only two of those have the magic value of "accessToken". They should be matched regardless of the parameter type (one String and one int), but the one with @RequestParam("someParameter") should not be matched. Strictly speaking, all method executions are matched, but runtime reflection eliminates the undesired ones. If your annotations would be on class or method level or on parameter types, we could match them directly in the pointcut without reflection, but in the case of parameter annotations this is beyond AspectJ's current (v1.8.4) capabilities and we have to use reflection, unfortunately.

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(* *(..)) 仅用于说明.你应该把范围缩小到你真正想要太匹配的方法.

Please note that my catch-all pointcut execution(* *(..)) is just for illustration. You should narrow it down to the methods you actually want too match.

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

另请参阅此答案,了解相关但稍微简单的问题,代码类似.

See also this answer on a related, but somewhat simpler question with similar code.

这篇关于从 ProceedingJoinPoint 检索参数值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆