我很难找到实现以下目标的明确方法。
对于来自客户端的请求范围操作调用,我们有一个很好的实现。这些操作预计会快速灵活,即<10 ms,并且任何繁重的工作都是异步执行的,独立于调用的操作,即在单独的线程或线程池中。
在执行这些线程时,我们需要将请求范围的变量注入它们。由于当这些线程执行时请求将完成,即线程执行在请求范围之外,我们不能直接注入请求范围的变量。
一种解决方案似乎是ServletScopes.scopeRequest方法。为了有效地使用它,我们编写了一个类 RequestScopePropagator ,它有效地将所有请求范围的对象引用复制到一个映射中,并在继续期间为它们播种。
我不相信这是否是正确的方法。有没有更合适的方式/方法?
import com.google.inject.Binding;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.Scope;
import com.google.inject.servlet.RequestScoped;
import com.google.inject.servlet.ServletScopes;
import com.google.inject.spi.BindingScopingVisitor;
public class RequestScopePropagator {
private final Map<Key<?>, Provider<?>> requestScopedValues = new HashMap<>
();
Logger logger =
Logger.getLogger(this.getClass().getName());
@Inject
RequestScopePropagator(Injector injector) {
for (Map.Entry<Key<?>, Binding<?>> entry : injector.getAllBindings().entrySet()) {
Key<?> key = entry.getKey();
Binding<?> binding = entry.getValue();
if (binding.acceptScopingVisitor(IS_REQUEST_SCOPED)) {
requestScopedValues.put(key, binding.getProvider());
}
}
}
private final BindingScopingVisitor<Boolean> IS_REQUEST_SCOPED = new BindingScopingVisitor<Boolean>() {
@Override
public Boolean visitScopeAnnotation( Class<? extends Annotation> scopeAnnotation) { return scopeAnnotation == RequestScoped.class; }
@Override
public Boolean visitScope(Scope scope) {
return scope == ServletScopes.REQUEST; }
@Override
public Boolean visitNoScoping() {
return false; }
@Override
public Boolean visitEagerSingleton() {
return false; }
};
public <T> Callable<T> continueRequest(Callable<T> callable) {
Map<Key<?>, Object> seedMap = new HashMap<Key<?>, Object>();
try {
for (Map.Entry<Key<?>, Provider<?>> entry : requestScopedValues.entrySet()) {
if (!entry.getKey().getTypeLiteral().getRawType().isAssignableFrom(HttpServletRequest.class)
&& !entry.getKey().getTypeLiteral().getRawType().isAssignableFrom(HttpServletResponse.class)
&& !entry.getKey().getTypeLiteral().getRawType().isAssignableFrom(Map.class))
seedMap.put(entry.getKey(), entry.getValue().get());
}
} catch (Exception e) {
logger.log(Level.SEVERE, "could not add request cope values in seed map for continuing request scope", e);
throw new AltAppOpsException("could not add request cope values in seed map for continuing request scope");
}
return ServletScopes.scopeRequest(callable, seedMap);
}
}