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

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

问题描述

在我的请求中,我有一个参数名称"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,我只有一点闲暇时间,所以我试图回答您的问题,而无需您回答我的所有问题.我这样做的方法是,我将 使用参数名称,但是尝试匹配带有注释@RequestParam("accessToken")的参数,即我将匹配注释类型和具有魔术名称"accessToken"的值,而不是方法参数名称,该值可能由于不知道您的方面的人的简单重构,由于在编译过程中从类文件中删除调试信息或由于混淆而可能会更改./p>

这里有一些自洽的示例代码,它们是针对AspectJ而不是Spring AOP进行测试的,但是后者的语法仍然是前者语法的子集:

使用主要方法对类进行采样:

有3种方法,所有这些方法都在其中一个参数上带有@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
 

另请参见此答案有关一个相似但代码简单的问题.

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 ?
        }
    }
}

Calling method:

public MyResponse saveUser(
    @RequestParam("accessToken") String accessToken,
    @RequestBody final UserDto userDto
) {
    // code 
}

I want to get this access token in AOP.

Thanks in advance.

解决方案

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.

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:

Sample class with main method:

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);
    }
}

Dummy helper class to make the code compile:

package de.scrum_master.app;

public class UserDto {}

Aspect:

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();
    }
}

Console output:

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天全站免登陆