1

我很难找到实现以下目标的明确方法。

对于来自客户端的请求范围操作调用,我们有一个很好的实现。这些操作预计会快速灵活,即<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);
}
}
4

0 回答 0