- 一个人应该如何使用ServletScopes.scopeRequest()?
- 如何获取Callable内部对象
@RequestScoped
的引用? seedMap
是什么意思?是否意味着重写默认绑定?- 此方法与ServletScopes.continueRequest()有什么区别?
回答
回答我的问题:
- ServletScopes.scopeRequest()运行在新请求范围可赎回。注意不要在不同范围内引用对象,否则最终会遇到线程问题,例如尝试使用已被另一个请求关闭的数据库连接。
static
或顶级课程是你的朋友。 - 您在将其传递到ServletScopes.scopeRequest()之前注入
Callable
。出于这个原因,你必须小心你的Callable
包含什么字段。更多关于下面的内容。 seedMap
允许您将对象注入到作用域中的非作用域对象。这是危险的,所以要注意你注入的内容。- ServletScopes.continueRequest()是类似的,只是它在现有的请求范围内运行。它获取当前HTTP范围的快照并将其包装在Callable中。原始HTTP请求完成(您从服务器返回一些响应),但是然后在单独的线程中异步完成实际操作。当稍后调用Callable时(在单独的线程中),它将有权访问原始的HttpServletRequest,但不能访问HTTP响应或会话。
那么,最好的办法是什么?
如果您不需要用户对象传递到Callable
:注射请求范围之外Callable
,并将其传递到ServletScopes.scopeRequest()。 Callable
可能只引用Provider<Foo>
而不是Foo
,否则最终将在实例之外注入实例。
如果您需要将用户对象传入Callable
,请继续阅读。假设你有一种将名字插入数据库的方法。有两种方法可以将名称传入Callable
。
方法1:
定义
InsertName
,一个Callable
是插入到数据库:@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(); } } }
绑定的所有用户对象传递使用子单元的用户对象一个子模块,并使用RequestInjector调用可调用范围。scopeRequest():
requestInjector.scopeRequest(InsertName.class, new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(Names.named("name")).toInstance("John"); } })
我们实例化一个
RequestInjector
请求外,它反过来,注入第二Callable
内部该请求。第二个Callable
可以直接引用Foo
(不需要提供者),因为它被注入请求范围内。
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);
}
}
方法2:注射引用Provider<Foo>
请求之外的Callable
。 call()
方法可以在get()
请求范围内的实际值。对象对象由一个seedMap
的方式通过了(我个人认为这种方法反直觉):
定义
InsertName
,一个Callable
是插入到数据库中。注意,与方法1,我们必须使用Providers
:@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(); } } }
创建要在传递类型的假绑定如果你没有,你会得到:
No implementation for String annotated with @com.google.inject.name.Named(value=name) was bound.
https://stackoverflow.com/a/9014552/14731解释了为什么这是必要的。填充与所需值seedMap:
ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.<Key<?>, Object>of(Key.get(String.class, Names.named("name")), "john");
调用
ServletScopes.scopeRequest()
:ServletScopes.scopeRequest(injector.getInstance(InsertName.class), seedMap);
- 1. Guice ServletScopes.scopeRequest和@RequestParameters测试时
- 2. 如何使用Apache2和PHP启用和使用HTTP PUT和DELETE?
- 3. 如何使用twitter和facebook使用openinviter?
- 4. 如何使用Ajax使用Flexslider和Wordpress?
- 5. 如何使用ID和面使用Solr
- 6. 如何使用Hibernate5和Vaadin8使用java.time.LocalDate?
- 7. 如何使用或不使用URL?和/
- 8. Eclipse如何使用和不使用JDK?
- 9. 如何使用使用JavaScript和GraphAPI
- 10. 如何使用preg_match和file_get_content使用PHP?
- 11. 如何使用jsdoc和gulp?
- 12. 如何使用PHP和MySQL
- 13. 如何使用devise和devise_security_extension?
- 14. 如何使用opencv和engine.h
- 15. 如何使用android.intent.action.CALL_PRIVILEGED和android.intent.action.NEW_OUTGOING_CALL?
- 16. 如何使用sqlite3和Python
- 17. 如何使用HttpRequest和HttpResponse
- 18. 如何使用Null求和
- 19. 如何使用PDT和WAMP
- 20. 如何使用IMAP和PHP
- 21. 如何使用QTranslate和Gtranslate
- 22. 如何使用domPDF和WordPress
- 23. 如何使用AJAX和JQuery
- 24. 如何使用NSLineSeparatorCharacter和NSParagraphSeparatorCharacter?
- 25. 如何使用CompareTo()和TreeSet()
- 26. 如何使用`for`和filereader?
- 27. 如何使用IRandomAccessStream和DataReader?
- 28. 如何使用HTML和JavaScript
- 29. 如何使用DataKeys和DataItemIndex
- 30. 如何使用setValue:forKeyPath和valueForKeyPath