2014-11-14 137 views
5

由于某种控制器的一个请求映射如何从Spring控制器的AOP建议中获取RequestMapping请求?

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

你怎么会在切面类检索方法值(RequestMethod.POST)?

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

谢谢

+0

获取'@ Controller' bean,获取调用的方法,检索注释,获取其'method'属性。 – 2014-11-14 15:45:53

回答

4

找到了解决方案。

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

要小心你导入哪一类。

+0

我仍然认为这不是它应该完成的方式。我自己的答案使用规范的AspectJ,并且不需要反射。 – kriegaex 2015-07-24 09:10:50

6

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

样品控制器主要方法:

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

看点:

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,切入点的&& execution(* *(..))部分在Spring AOP中可能不需要,因为它只是知道执行切入点。在AspectJ中,您需要排除call()和其他类型的切入点,因为AspectJ更强大。它虽然没有伤害,并且更安全,更明确。

控制台输出:

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 

编辑:被交换的参数,从而使连接点的第一通知方法的参数,因为Spring AOP的似乎该订单上坚持而AspectJ的没有。

+0

我试过你的解决方案,它似乎没有工作。在切入点处得到错误:: 0正式解绑。 – 2014-11-17 19:41:17

+0

它适合我。您在复制和粘贴操作中犯了错误吗? – kriegaex 2014-11-17 23:22:50

+1

前一段时间有人提到,对于Spring AOP,他不得不在建议签名的开头,而不是结尾处加入'JoinPoint'参数。我怀疑这是真的,但你可以尝试。我绝不是Spring专家。 – kriegaex 2014-11-17 23:25:38

相关问题