Come iniettare un object nel contesto della richiesta di jersey?

Ho questo scenario in cui voglio scrivere un filtro e voglio che questo filtro inserisca qualche object nella richiesta corrente e lo trasmetta in modo che quando la class di risorsa ottiene la richiesta possa usare l’object.

Classe filtro

@Override public void filter(ContainerRequestContext request) throws IOException { MyObject obj = new MyObject(); // Inject MyObject to request which I dont know how } 

Classe di risorse

 @PUT @Consumes("application/json") @Path("/") public String create( JSONParam sample, @Context MyObject obj) { System.out.println(obj.getName()); return ""; } 

Potresti semplicemente usare ContainterRequestContext.setProperty(String, Object) . Quindi iniettare semplicemente ContainerRequestContext

 @Override public void filter(ContainerRequestContext crc) throws IOException { MyObject obj = new MyObject(); crc.setProperty("myObject", myObject); } @POST public Response getResponse(@Context ContainerRequestContext crc) { return Response.ok(crc.getProperty("myObject")).build(); } 

Un’altra opzione per iniettare direttamente MyObject consiste nell’utilizzare le funzionalità di Jersey 2 offerte da HK2.

Creare una factory, iniettare ContainerRequestContext e restituire MyObject . Per esempio

 import javax.inject.Inject; import javax.ws.rs.container.ContainerRequestContext; import jetty.plugin.test.domain.MyObject; import org.glassfish.hk2.api.Factory; public class MyObjectFactory implements Factory { private final ContainerRequestContext context; @Inject public MyObjectFactory(ContainerRequestContext context) { this.context = context; } @Override public MyObject provide() { return (MyObject)context.getProperty("myObject"); } @Override public void dispose(MyObject t) {} } 

Devi quindi bind la fabbrica:

 public class InjectApplication extends ResourceConfig { public InjectApplication() { ... register(new AbstractBinder(){ @Override protected void configure() { bindFactory(MyObjectFactory.class) .to(MyObject.class) .in(RequestScoped.class); } }); } } 

Con la stessa impostazione della proprietà come nell’esempio del filtro sopra, puoi semplicemente iniettare MyObject con @Context

 @GET public Response getTest(@Context MyObject myObject) { return Response.ok(myObject.getMessage()).build(); } 

  • Vedi di più su Custom Injection

AGGIORNARE

Si prega di vedere questa domanda per un problema con questa implementazione.

Guarda anche:

  • Se stai usando web.xml invece di un ResourceConfig

Ho una soluzione a questo che non richiede un contenitore DI, ma offre ancora gran parte del vantaggio.

Ci sono due parti. Il primo è come ottenere istanze nel meccanismo di iniezione di @Context invece di fornire classi nell’object ApplicationConfig.

Ecco una tecnica per farlo:

 private static class CustomContextResteasyBootstrap extends org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap{ private final Map, Object> additionalContextObjects = new HashMap, Object>(); public  CustomContextResteasyBootstrap addContextObject(Class clazz, E obj){ additionalContextObjects.put(clazz, obj); return this; } @Override public void contextInitialized(ServletContextEvent event) { super.contextInitialized(event); deployment.getDispatcher().getDefaultContextObjects().putAll(additionalContextObjects); } } 

e lo usi in questo modo:

  webAppContext.addEventListener( new CustomContextResteasyBootstrap() .addContextObject(MyCustom.class, myCustom) .addContextObject(AnotherCustom.class, anotherCustom) // additional objects you wish to inject into the REST context here ); 

ora puoi usare quelle classi con l’annotazione @Context:

 @GET public MyCustom echoService(@Context MyCustom custom) { return custom; } 

La prossima parte del puzzle è come fornire oggetti di contesto per richiesta. Per fare ciò, aggiungi il seguente codice da qualche parte vicino alla parte superiore della gerarchia di chiamate jax-rs (in pratica, tutto ciò che viene chiamato sotto questa linea avrà accesso all’object contesto):

  ResteasyProviderFactory.pushContext(MyContextSpecific.class, new MyContextSpecific()); 

È quindi ansible fare riferimento a questo tramite iniezione ovunque sotto quel livello:

 @GET public String contextSpecificEchoService(@Context MyContextSpecific contextSpecific) { return custom.toString(); } 

Questo è il DI di povero uomo, ma funziona molto bene per i server di rest integrati.