2014-11-14 17 views
5

dato qualche tipo di controller con una mappatura richiestaCome si ottiene la richiesta di RequestMapping in consigli AOP da un controller Spring?

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

Come vi recuperare il valore del metodo (RequestMethod.POST) nella classe aspetto?

Desidero tenere traccia di tutti i metodi del controller che eseguono una richiesta POST.

Grazie

+0

Ottenere il bean '@ Controller', ottenere il metodo richiamato, recuperare l'annotazione, ottenere il suo attributo' method'. –

risposta

4

Trovato la soluzione.

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

Fai attenzione a quale classe importi.

+0

Continuo a pensare che questo non sia il modo in cui dovrebbe essere fatto. La mia risposta usa AspectJ canonico e non richiede riflessione. – kriegaex

6

@ AL13N: la propria risposta è corretta, ma non è necessario utilizzare la riflessione se si associa l'annotazione a un parametro. Ecco un esempio in POJO + AspectJ. In Spring AOP dovrebbe essere lo stesso, però:

regolatore di esempio con metodo 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(); 
    } 
} 

Dimensioni:

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

proposito, la parte && execution(* *(..)) del pointcut è probabilmente non è necessario in Spring AOP perché conosce solo i pointcut di esecuzione in ogni caso. In AspectJ è necessario escludere call() e altri tipi di collegamenti perché AspectJ è più potente. Non fa male però ed è più sicuro ed esplicito.

uscita della console:

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: parametri invertiti in modo da rendere il joinpoint il primo parametro del metodo consigli, perché la primavera AOP sembra insistere su questo ordine, mentre AspectJ non lo fa.

+0

Ho provato la soluzione e non sembra funzionare. Ottenere un errore a :: 0 formale non associato in pointcut. –

+0

Funziona per me. Hai commesso un errore nella tua azione copia e incolla? – kriegaex

+1

Qualcuno ha citato qualche tempo fa che per Spring AOP ha dovuto inserire il parametro 'JoinPoint' all'inizio della firma del consiglio invece che alla fine. Dubito che sia vero, ma puoi provare. Non sono affatto un esperto di primavera. – kriegaex