- ¿Cómo se supone que uno debe usar ServletScopes.scopeRequest()?
- ¿Cómo obtengo una referencia a un objeto
@RequestScoped
dentro del Llamado? - ¿Cuál es el punto de
seedMap
? ¿Está destinado a anular el enlace predeterminado? - ¿Cuál es la diferencia entre este método y ServletScopes.continueRequest()?
Respuesta
responder a mi propia pregunta:
- ServletScopes.scopeRequest() dirige una rescatable en una solicitud alcance nueva. Tenga cuidado de no hacer referencia a los objetos en diferentes ámbitos, de lo contrario terminará con problemas de enhebrado como intentar usar una conexión de base de datos que ya ha sido cerrada por otra solicitud.
static
o las clases de nivel superior son tus amigos aquí. - Usted inyecta el
Callable
antes de pasarlo al ServletScopes.scopeRequest(). Por este motivo, debe tener cuidado con los campos que contiene suCallable
. Más sobre esto a continuación. seedMap
le permite inyectar objetos sin alcance en el alcance. Esto es peligroso, así que ten cuidado con lo que inyectas.- ServletScopes.continueRequest() es similar, excepto que se ejecuta dentro de un alcance de solicitud existente. Toma una instantánea del alcance de HTTP actual y lo envuelve en un Callable. La solicitud HTTP original se completa (devuelve alguna respuesta del servidor) pero luego completa la operación real de forma asincrónica en una secuencia separada. Cuando se invoca el Callable en algún momento posterior (en ese hilo separado), tendrá acceso al HttpServletRequest original, pero no a la respuesta o sesión HTTP.
Entonces, ¿cuál es la mejor manera de hacerlo?
Si no necesita pasar por el usuario-objetos en el Callable
: Inyectar la Callable
fuera del ámbito de la petición, y se pasa dentro ServletScopes.scopeRequest(). El Callable
solo puede hacer referencia a Provider<Foo>
en lugar de a Foo
, de lo contrario, terminará con instancias inyectadas fuera del alcance de la solicitud.
Si necesita pasar objetos de usuario en el Callable
, siga leyendo.
Digamos que tiene un método que inserta nombres en una base de datos. Hay dos maneras para que pasemos el nombre al Callable
.
Enfoque 1: Pass user-objetos utilizando un módulo de niño:
Definir
InsertName
, unCallable
que se inserta en la base de datos:@RequestScoped private static class InsertName implements Callable<Boolean> { private final String name; private final Connection connection; @Inject public InsertName(@Named("name") String name, Connection connection) { this.name = name; this.connection = connection; } @Override public Boolean call() { try { boolean nameAlreadyExists = ...; if (!nameAlreadyExists) { // insert the name return true; } return false; } finally { connection.close(); } } }
prender a todos los usuarios-objetos en un módulo hijo y alcance el llamante utilizando RequestInjector.scopeRequest():
requestInjector.scopeRequest(InsertName.class, new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(Names.named("name")).toInstance("John"); } })
Nos instanciar un
RequestInjector
fuera de la solicitud y que, a su vez, se inyecta una segundaCallable
dentro la solicitud. El segundoCallable
puede hacer referencia directamente alFoo
(sin necesidad de proveedores) porque se inyecta dentro del alcance de la solicitud.
import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.servlet.ServletScopes;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Callable;
/**
* Injects a Callable into a non-HTTP request scope.
* <p/>
* @author Gili Tzabari
*/
public final class RequestInjector
{
private final Map<Key<?>, Object> seedMap = Collections.emptyMap();
private final Injector injector;
/**
* Creates a new RequestInjector.
*/
@Inject
private RequestInjector(Injector injector)
{
this.injector = injector;
}
/**
* Scopes a Callable in a non-HTTP request scope.
* <p/>
* @param <V> the type of object returned by the Callable
* @param callable the class to inject and execute in the request scope
* @param modules additional modules to install into the request scope
* @return a wrapper that invokes delegate in the request scope
*/
public <V> Callable<V> scopeRequest(final Class<? extends Callable<V>> callable,
final Module... modules)
{
Preconditions.checkNotNull(callable, "callable may not be null");
return ServletScopes.scopeRequest(new Callable<V>()
{
@Override
public V call() throws Exception
{
return injector.createChildInjector(modules).getInstance(callable).call();
}
}, seedMap);
}
}
Enfoque 2: Inyectar una Callable
fuera de la petición que hace referencia a Provider<Foo>
. El método call()
puede entonces get()
los valores reales dentro del alcance de la solicitud. Los objetos de objetos se pasan en por medio de un seedMap
(personalmente encuentro este enfoque contrario a la intuición):
Definir
InsertName
, unCallable
que se inserta en la base de datos. Nótese que a diferencia de enfoque 1, debemos usarProviders
:@RequestScoped private static class InsertName implements Callable<Boolean> { private final Provider<String> name; private final Provider<Connection> connection; @Inject public InsertName(@Named("name") Provider<String> name, Provider<Connection> connection) { this.name = name; this.connection = connection; } @Override public Boolean call() { try { boolean nameAlreadyExists = ...; if (!nameAlreadyExists) { // insert the name return true; } return false; } finally { connection.close(); } } }
crean vinculaciones falsas de los tipos que desea pasar en Si no obtendrá:.
No implementation for String annotated with @com.google.inject.name.Named(value=name) was bound.
https://stackoverflow.com/a/9014552/14731 explica por qué esto es necesario.Rellenar la seedMap con los valores deseados:
ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.<Key<?>, Object>of(Key.get(String.class, Names.named("name")), "john");
Invoke
ServletScopes.scopeRequest()
:ServletScopes.scopeRequest(injector.getInstance(InsertName.class), seedMap);
- 1. ¿Cómo usar Lucene y JPA?
- 2. BitmapCache? ¿Cuándo y cómo usar?
- 3. Cómo usar NSFetchedResultsController y UISearchDisplayController
- 4. Cómo importar y usar com.sun.jdi.VirtualMachine
- 5. Cómo usar setInterval y clearInterval?
- 6. Cómo usar matrix.preScale (x, y)
- 7. Cómo usar bind1st y bind2nd?
- 8. Cómo usar UINib para crear instancias y usar UITableViewCells personalizadas
- 9. Cómo usar y cuándo es bueno usar memmove en C?
- 10. cuándo usar Tarea y cuándo usar Subproceso?
- 11. cómo usar braintree con rieles y activemerchant
- 12. hibernate restrictions.in con y, cómo usar?
- 13. cómo usar ByteArrayOutputStream y DataOutputStream simultáneamente (Java)
- 14. Cómo usar IsKeyboardFocusWithin y IsSelected together?
- 15. ¿Cuándo y cómo usar constantes en PHP?
- 16. Capistrano implementa cómo usar use_sudo y admin_runner
- 17. ¿Cómo usar Mercurial, Maven y Eclipse juntos?
- 18. ¿Cómo se puede usar directlabels y ggplot2?
- 19. Cómo escapar y al usar sed
- 20. Cómo y cuándo usar una clase abstracta
- 21. ¿Cómo usar ReCaptcha con MVC3 y navaja?
- 22. ¿Cómo usar JUnit y Hamcrest juntos?
- 23. Cómo usar S_ISREG() y S_ISDIR() POSIX Macros?
- 24. C - Cómo usar aio_read() y aio_write()
- 25. Hibernate: cómo usar CONCAT y GROUP_CONCAT
- 26. eclipse link y log4j: cómo usar ambos
- 27. ¿Dónde y cómo usar clases anidadas?
- 28. express 3.0 cómo usar app.locals.use y res.locals.use
- 29. Secuela: Cómo usar el grupo y contar
- 30. ¿Cómo usar Websockets con Pyramid y socket.io?