- Come si suppone di utilizzare ServletScopes.scopeRequest()?
- Come si ottiene un riferimento a un oggetto
@RequestScoped
all'interno di Callable? - Qual è il punto di
seedMap
? Significa ignorare il binding predefinito? - Qual è la differenza tra questo metodo e ServletScopes.continueRequest()?
risposta
Rispondendo alla mia domanda:
- ServletScopes.scopeRequest() gestisce una Callable in una richiesta ambito nuova. Fai attenzione a non fare riferimento a oggetti su ambiti diversi, altrimenti ti ritroverai con problemi di thread come provare a utilizzare una connessione al database che è già stata chiusa da un'altra richiesta.
static
o le classi di primo livello sono i tuoi amici qui. - Si inietta lo
Callable
prima di passarlo a ServletScopes.scopeRequest(). Per questo motivo, devi stare attento a quali campi contiene il tuoCallable
. Maggiori informazioni su questo sotto. seedMap
consente di iniettare oggetti senza ambito nell'ambito. Questo è pericoloso, quindi fai attenzione a ciò che inietti.- ServletScopes.continueRequest() è simile tranne che viene eseguito all'interno di uno scope di richiesta esistente. Prende un'istantanea dell'ambito HTTP corrente e lo avvolge in un Callable. La richiesta HTTP originale completa (si restituisce una risposta dal server), ma si completa l'operazione effettiva in modo asincrono in una thread separata. Quando il Callable viene richiamato in un secondo momento (in quel thread separato) avrà accesso al HttpServletRequest originale ma non alla risposta o sessione HTTP.
Allora, qual è il modo migliore per farlo?
Se non è necessario passare user-oggetti nel Callable
: Iniettare il Callable
di fuori della portata richiesta e passa in ServletScopes.scopeRequest(). Callable
può fare riferimento solo a Provider<Foo>
anziché a Foo
, altrimenti si finisce con istanze iniettate al di fuori dell'ambito della richiesta.
Se è necessario passare oggetti utente nello Callable
, continuare a leggere.
Supponiamo di avere un metodo che inserisce i nomi in un database. Ci sono due modi per noi di passare il nome nello Callable
.
Approccio 1: Pass user-oggetti utilizzando un modulo bambino:
Definire
InsertName
, unCallable
che inserisce nel database:@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(); } } }
Bind tutti gli utenti-oggetti in un modulo figlio e scope il callable usando RequestInjector.scopeRequest():
requestInjector.scopeRequest(InsertName.class, new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(Names.named("name")).toInstance("John"); } })
istanziamo un
RequestInjector
fuori della richiesta e, a sua volta, inietta una secondaCallable
all'interno richiesta. Il secondoCallable
può fare riferimento direttamente alloFoo
(non è necessario per i provider) poiché è inserito all'interno dell'ambito della richiesta.
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);
}
}
Approccio 2: Iniettare un Callable
di fuori della domanda che fa riferimento Provider<Foo>
. Il metodo call()
può quindi get()
i valori effettivi all'interno dell'ambito della richiesta. Gli oggetti oggetto sono passati in per mezzo di un seedMap
(Personalmente trovo questo metodo intuitivo):
Definire
InsertName
, unCallable
che inserisce nel database. Si noti che a differenza di approccio 1, dobbiamo usareProviders
:@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(); } } }
creare associazioni fasulle per i tipi che si desidera passare Se non si otterrà:.
No implementation for String annotated with @com.google.inject.name.Named(value=name) was bound.
https://stackoverflow.com/a/9014552/14731 spiega perché questo è necessario.Popolare la seedMap con i valori desiderati:
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. Come utilizzare emberjs e internazionalizzazione
- 2. Come utilizzare Math.cos() e Math.sin()?
- 3. Come importare e utilizzare com.sun.jdi.VirtualMachine
- 4. Come installare e utilizzare Scrooge
- 5. Come utilizzare NSFetchedResultsController e UISearchDisplayController
- 6. Come utilizzare SqlAzureExecutionStrategy e "nolock"
- 7. Come utilizzare NotificationCompat.Builder e startForeground?
- 8. Come definire e utilizzare% come operatore prefisso?
- 9. Come utilizzare UINib per creare un'istanza e utilizzare UITableViewCells personalizzate
- 10. Come utilizzare creare e utilizzare un UIImageAsset in iOS 8
- 11. Quando utilizzare Meteor.methods e utilizzare gli stub
- 12. Quando utilizzare JMS e quando utilizzare REST?
- 13. Come utilizzare IsKeyboardFocusWithin e IsSelected insieme?
- 14. Come utilizzare WMS e WFS in Android
- 15. Come utilizzare Enums in getter e setter?
- 16. Come utilizzare il nuovo HttpSessionStateWrapper e HttpSessionStateBase?
- 17. Come utilizzare kbhit e getch (programmazione C)
- 18. eclipse link e log4j: come utilizzare entrambi
- 19. Hibernate: come utilizzare CONCAT e GROUP_CONCAT
- 20. Come compilare e utilizzare GLib con MinGW
- 21. Come utilizzare LibreOffice Calc e Python?
- 22. come utilizzare GC.KeepAlive() e per quale scopo
- 23. Dove ottenere e come utilizzare zend_pdf standalone
- 24. Come creare e utilizzare Enum in Mongoose
- 25. Come rifiutare (e utilizzare correttamente) le promesse?
- 26. confuso come utilizzare AES e HMAC
- 27. Come utilizzare Qt WebEngine e QWebChannel?
- 28. Come utilizzare le gemme Devise e Doorkeeper?
- 29. Come utilizzare AES_ENCRYPT e AES_DECRYPT in MySQL
- 30. Capistrano distribuire come utilizzare use_sudo e admin_runner