java 如何从 Spring 控制器获取 AOP 建议中的 RequestMapping 请求?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26933623/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 10:54:25  来源:igfitidea点击:

How do you get RequestMapping request in AOP advice from a Spring controller?

javaspringhttploggingaop

提问by Andy Leung

Given some kind of controller with a request mapping

给定某种带有请求映射的控制器

@RequestMapping(value="/some/path", method=RequestMethod.POST)

How would you retrieve the method value (RequestMethod.POST) in the aspect class?

您将如何检索方面类中的方法值 (RequestMethod.POST)?

I want to keep track of all the controller methods that perform a POST request.

我想跟踪执行 POST 请求的所有控制器方法。

Thanks

谢谢

采纳答案by Andy Leung

Found the solution.

找到了解决办法。

import org.aspectj.lang.reflect.MethodSignature;
import java.lang.reflect.Method;

@Pointcut("within(@org.springframework.stereotype.Controller *)")
public void controller() {}

// In advice
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature .getMethod();
RequestMethod[] requestMethods = method.getAnnotation(RequestMapping.class).method();

Be careful of which class you import.

请注意您导入的类。

回答by kriegaex

@AL13N: Your own answer is correct, but you do not need to use reflection if you just bind the annotation to a parameter. Here is an example in POJO + AspectJ. In Spring AOP it should be the same, though:

@AL13N:您自己的答案是正确的,但是如果您只是将注释绑定到参数,则不需要使用反射。这是 POJO + AspectJ 中的一个示例。但是在 Spring AOP 中它应该是相同的:

Sample controller with main method:

带有 main 方法的示例控制器:

package de.scrum_master.app;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MyController {
    @RequestMapping(value="/some/path", method=RequestMethod.POST)
    public void foo() {
        System.out.println("foo");
    }
    public void bar() {
        System.out.println("bar");
    }

    public static void main(String[] args) {
        MyController controller = new MyController();
        controller.foo();
        controller.bar();
    }
}

Aspect:

方面:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.web.bind.annotation.RequestMapping;

public aspect RequestMappingInterceptor {
    @Pointcut(
        "within(@org.springframework.stereotype.Controller *) && " +
        "@annotation(requestMapping) && " +
        "execution(* *(..))"
    )
    public void controller(RequestMapping requestMapping) {}

    @Before("controller(requestMapping)")
    public void advice(JoinPoint thisJoinPoint, RequestMapping requestMapping) {
        System.out.println(thisJoinPoint);
        System.out.println("  " + requestMapping);
        System.out.println("  " + requestMapping.method()[0]);
    }
}

BTW, the && execution(* *(..))part of the pointcut is probably not necessary in Spring AOP because it just knows execution pointcuts anyway. In AspectJ you need to exclude call()and other types of pointcuts because AspectJ is more powerful. It does not hurt though and is safer and more explicit.

顺便说一句,&& execution(* *(..))切入点的部分在 Spring AOP 中可能不是必需的,因为无论如何它只知道执行切入点。在 AspectJ 中,您需要排除call()其他类型的切入点,因为 AspectJ 更强大。虽然它不会受到伤害,并且更安全,更明确。

Console output:

控制台输出:

execution(void de.scrum_master.app.MyController.foo())
  @org.springframework.web.bind.annotation.RequestMapping(headers=[], name=, value=[/some/path], produces=[], method=[POST], params=[], consumes=[])
  POST
foo
bar

Edit:Swapped parameters so as to make the joinpoint the first advice method parameter, because Spring AOP seems to insist on this order while AspectJ does not.

编辑:交换参数以使连接点成为第一个建议方法参数,因为 Spring AOP 似乎坚持这个顺序,而 AspectJ 没有。