2015-03-22 35 views
7

Sto faticando un po 'a capire come le annotazioni dell'intercettatore di riposo possono aggiungere valori diversi che sono successivamente visibili nel filtro. Dato il codice qui sotto, mi aspetterei che una volta nel filtro i valori delle autorizzazioni abbiano foo e bar al loro interno, tuttavia sono vuoti. Qualsiasi aiuto sarebbe molto apprezzato.Ottenere i valori di annotazione della classe di risorse all'interno di ContainerRequestFilter

annotazione

package edu.psu.swe.fortress.poc.interceptor; 

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

import javax.enterprise.util.Nonbinding; 
import javax.ws.rs.NameBinding; 

@NameBinding 
@Target({ElementType.TYPE, ElementType.METHOD}) 
@Retention(value=RetentionPolicy.RUNTIME) 
public @interface FortressProtected 
{ 
    @Nonbinding String[] permissions() default {}; 
} 

Filtro

package edu.psu.swe.fortress.poc.interceptor; 

import java.io.IOException; 
import java.lang.annotation.Annotation; 

import javax.ws.rs.container.ContainerRequestContext; 
import javax.ws.rs.container.ContainerRequestFilter; 
import javax.ws.rs.ext.Provider; 

@Provider 
@FortressProtected 
public class FortressAuthorizer implements ContainerRequestFilter 
{ 

    @Override 
    public void filter(ContainerRequestContext requestContext) throws  IOException 
    { 
    System.out.println("In the interceptor"); 
    Class<?> clazz = this.getClass(); 
    FortressProtected annotation = clazz.getAnnotation(edu.psu.swe.fortress.poc.interceptor.FortressProtected.class); 

    System.out.println("Annotation? " + clazz.isAnnotation()); 

    for (Annotation a : clazz.getAnnotations()) 
    { 
     System.out.println(a); 
    } 

    for (String s : annotation.permissions()) 
    { 
     System.out.println(s); 
    } 
    } 
} 

App config

package edu.psu.swe.fortress.poc.rest; 

import java.util.HashSet; 
import java.util.Set; 

import javax.ws.rs.ApplicationPath; 
import javax.ws.rs.core.Application; 

import edu.psu.swe.fortress.poc.interceptor.FortressAuthorizer; 
import edu.psu.swe.fortress.poc.interceptor.FortressProtected; 

@ApplicationPath("") 
public class FortressTestApp extends Application 
{ 
    private Set<Class<?>> clazzez_ = new HashSet<>(); 
    { 
    clazzez_.add(ResourceImpl.class); 
    clazzez_.add(FortressProtected.class); 
    clazzez_.add(FortressAuthorizer.class); 
    } 
    public Set<Class<?>> getClasses() 
    { 
    return clazzez_; 
    } 
} 

classe Resource

package edu.psu.swe.fortress.poc.rest; 

import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.Produces; 

import edu.psu.swe.fortress.poc.interceptor.FortressProtected; 

@FortressProtected(permissions={"foo", "bar"}) 
@Path("tests") 
public class ResourceImpl 
{ 
    @GET 
    @Produces("application/text") 
    public String getHello() 
    { 
    FortressProtected annotation = this.getClass().getAnnotation(edu.psu.swe.fortress.poc.interceptor.FortressProtected.class); 

    System.out.println(annotation.toString()); 

    return "hello"; 
    } 
} 

uscita Log assomiglia:

15: 59: 55.223 INFO [stdout] (default task-9) @ edu.psu.swe.fortress.poc.interceptor.FortressProtected (permessi = []) 15: 59: 55.229 INFO [stdout] (predefinito compito-9) @ edu.psu.swe.fortress.poc.interceptor.FortressProtected (autorizzazioni = [foo, bar])

Grazie in anticipo.

risposta

12

Guardate questa nel filtro

Class<?> clazz = this.getClass(); 
FortressProtected annotation = clazz.getAnnotation(FortressProtected.class); 

this.getClass() corrisponde alla classe del filtro (la cui annotazione ha alcun valore). È invece necessario ottenere l'annotazione sul ResourceImpl

Un paio di opzioni. È possibile utilizzare esplicitamente ResourceImpl.class.getAnnotation(...). Ma il problema con questo è che una volta che si associa più di una classe, come si fa a far corrispondere la classe corrispondente alla richiesta. Per questo motivo, la prossima opzione è più praticabile.

Quello che fai è iniettare ResourceInfo. Con questo, puoi chiamare i suoi metodi getResourceMethod o getResourceClass. Questi metodi restituiscono rispettivamente il metodo e la classe abbinati. È quindi possibile verificare l'annotazione a livello di classe e il livello del metodo (poiché è anche possibile eseguire il binding a livello di metodo). Quindi potresti avere qualcosa di più:

@Provider 
@FortressProtected 
public class FortressAuthorizer implements ContainerRequestFilter { 

    @Context 
    ResourceInfo resourceInfo; 

    @Override 
    public void filter(ContainerRequestContext requestContext) throws IOException { 

    Class<?> resourceClass = resourceInfo.getResourceClass(); 
    FortressProtected classAnnot = resourceClass.getAnnotation(FortressProtected.class); 
    if (classAnnot != null) { 
     // do something with annotation 
    } 

    Method resourceMethod = resourceInfo.getResourceMethod(); 
    FortressProtected methodAnnot = resourceMethod.getAnnotation(FortressProtected.class); 
    if (methodAnnot != null) { 
     // do something with annotation 
    } 
    } 
} 
+2

Questo è esattamente quello che stavo cercando. Grazie mille. –