Jak wprowadzić obiekt do kontekstu żądania?

Mam taki scenariusz, w którym chcę napisać filtr i chcę, aby ten filtr wstawił jakiś obiekt do bieżącego żądania i przekazał go dalej, aby gdy Klasa zasobów otrzyma żądanie, mogła użyć tego obiektu.

Klasa filtra

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

Klasa Zasobów

@PUT @Consumes("application/json")
@Path("/")
public String create(
        JSONParam sample,
        @Context MyObject obj) {

    System.out.println(obj.getName());

    return "";
}
Author: Paul Samsotha, 2014-12-27

2 answers

Możesz po prostu użyć ContainterRequestContext.setProperty(String, Object). Następnie wystarczy wstrzyknąć 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();
}

Inną opcją bezpośredniego wtrysku MyObject jest skorzystanie z funkcjonalności HK2.

Utworzyć fabrykę wstrzyknąć ContainerRequestContext i zwrócić MyObject. Na przykład

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) {}  
}

Następnie musisz związać fabrykę:

public class InjectApplication extends ResourceConfig {

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

Z tym samym ustawieniem właściwości jak w powyższym przykładzie filtra, możesz po prostu wprowadzić MyObject z @Context

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


UPDATE

Proszę zobaczyć to pytanie dla problemu z tą implementacją.

Zobacz Też:

 35
Author: Paul Samsotha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-29 10:00:33

Mam na to rozwiązanie, które nie wymaga kontenera DI, ale nadal daje większość korzyści.

Są dwie części. Pierwszy to sposób na wprowadzenie instancji do mechanizmu wtrysku @ Context zamiast dostarczania klas w obiekcie ApplicationConfig.

Oto technika na to:

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

}

I używasz go w ten sposób:

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

Teraz możesz używać tych klas z adnotacją @ Context:

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

Kolejna część układanki to jak podaj obiekty kontekstowe na żądanie. Aby to zrobić, dodaj następujący kod gdzieś u góry hierarchii wywołań jax-rs (zasadniczo wszystko, co zostanie wywołane poniżej tej linii, uzyska dostęp do obiektu context):

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

Możesz następnie odwołać się do tego poprzez wstrzyknięcie w dowolnym miejscu poniżej tego poziomu:

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

To jest DI biednego człowieka, ale działa naprawdę dobrze dla Wbudowanych serwerów rest.

 0
Author: Kevin Day,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-05 22:42:31