[英]How to inject an object into jersey request context?
我有這個場景,我想寫一個過濾器,我希望這個過濾器將一些對象插入當前請求並傳遞它,以便當資源類獲取請求時,它可以使用該對象。
過濾類
@Override
public void filter(ContainerRequestContext request) throws IOException {
MyObject obj = new MyObject();
// Inject MyObject to request which I dont know how
}
資源類
@PUT @Consumes("application/json")
@Path("/")
public String create(
JSONParam sample,
@Context MyObject obj) {
System.out.println(obj.getName());
return "";
}
您可以使用ContainterRequestContext.setProperty(String, Object)
。 然后只注入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();
}
直接注入MyObject
另一個選擇是使用Jersey 2提供的HK2功能。
創建一個工廠,注入ContainerRequestContext
並返回MyObject
。 例如
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<MyObject> {
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) {}
}
然后你需要綁定工廠:
public class InjectApplication extends ResourceConfig {
public InjectApplication() {
...
register(new AbstractBinder(){
@Override
protected void configure() {
bindFactory(MyObjectFactory.class)
.to(MyObject.class)
.in(RequestScoped.class);
}
});
}
}
使用與上面的過濾器示例相同的屬性設置,然后可以使用@Context
注入MyObject
@GET
public Response getTest(@Context MyObject myObject) {
return Response.ok(myObject.getMessage()).build();
}
Custom Injection
查看更多信息 也可以看看:
我有一個解決方案,不需要DI容器,但仍然提供了大部分好處。
有兩個部分。 第一個是如何將實例引入@Context注入機制,而不是在ApplicationConfig對象中提供類。
這是一種技術:
private static class CustomContextResteasyBootstrap extends org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap{
private final Map<Class<?>, Object> additionalContextObjects = new HashMap<Class<?>, Object>();
public <E> CustomContextResteasyBootstrap addContextObject(Class<? super E> clazz, E obj){
additionalContextObjects.put(clazz, obj);
return this;
}
@Override
public void contextInitialized(ServletContextEvent event) {
super.contextInitialized(event);
deployment.getDispatcher().getDefaultContextObjects().putAll(additionalContextObjects);
}
}
你像這樣使用它:
webAppContext.addEventListener(
new CustomContextResteasyBootstrap()
.addContextObject(MyCustom.class, myCustom)
.addContextObject(AnotherCustom.class, anotherCustom)
// additional objects you wish to inject into the REST context here
);
現在您可以將這些類與@Context注釋一起使用:
@GET
public MyCustom echoService(@Context MyCustom custom) {
return custom;
}
這個難題的下一部分是如何提供每個請求的上下文對象。 為此,請在jax-rs調用層次結構頂部附近添加以下代碼(基本上,在此行下方調用的任何內容都將訪問上下文對象):
ResteasyProviderFactory.pushContext(MyContextSpecific.class, new MyContextSpecific());
然后,您可以通過注射在該級別以下的任何位置引用此
@GET
public String contextSpecificEchoService(@Context MyContextSpecific contextSpecific) {
return custom.toString();
}
這是窮人的DI,但它對嵌入式休息服務器非常有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.