web-dev-qa-db-ja.com

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で取得したいと思います。

前もって感謝します。

9
Shamseer PC

さて、シャムシアー、私は少し暇があるので、あなたが私のコメントから私のすべての質問に答えることなくあなたの質問に答えようとしています。私がこれを行う方法は、ではなくパラメータ名を使用しますが、一致させようとしますアノテーション付きのパラメーター@RequestParam("accessToken")、つまり、アノテーションのタイプと値を、知らない人の単純なリファクタリングによって変更される可能性のあるメソッドパラメーター名ではなく、「accessToken」という魔法の名前で照合します。コンパイル中にクラスファイルからデバッグ情報を取り除くため、または難読化のために、あなたの側面。

これは、Spring AOPではなくAspectJに対してテストされた、一貫性のあるサンプルコードですが、後者の構文は、とにかく前者の構文のサブセットです。

mainメソッドを使用したサンプルクラス:

3つのメソッドがあり、そのすべてのパラメーターの1つに_@RequestParam_アノテーションがありますが、「accessToken」の魔法の値を持つのはそのうちの2つだけです。パラメータタイプ(1つはStringと1つは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
_

関連するが、同様のコードを使用したやや単純な質問については、 この回答 も参照してください。

23
kriegaex

メソッドへのパラメーターとして取得する引数を取得するには、次のような方法を試すことができます。

Object[] methodArguments = joinPoint.getArgs();
6
SMA