簡體   English   中英

如何將對象注入澤西請求上下文?

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


UPDATE

有關實現的問題,請參閱此問題

也可以看看:

我有一個解決方案,不需要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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM