我们正在Tomcat上使用JSF 2和Weld Cdi开发一个Web前端。
现在我在并行执行多个web服务以优化请求时间方面遇到了问题。
用户可以选择多个项目形成一个列表。
对于每个选中的项目,流程使用list键作为参数从一个web服务收集它的信息。
我目前的方法是使用Producer,它返回web服务端口接口,该接口被注入到bean中。对于每个选定的键,bean在循环中调用该web服务。
@Inject
private WSAnzeigeAssetsummen serviceAccess;
:
for ( Integer pfNr : sessionKeys.getPfnrList() ) {
summaryTable = serviceAccess.execute(snr, pfnr, requestType, "", desiredRows, userName);
processResult(summaryTable):
}
为了更快,我尝试使用ExecutorService和尽可能多的工作者,它们返回期货。
这个构造的问题是,我不能将服务端口注入到worker中,因为worker没有被管理。手工创建服务端口可以工作,但不受欢迎,因为它忽略了生产者类。
同样,在测试时,不可能注入虚拟服务端口,它提供预定义的结果集。
由于我没有发现任何关于在tomcat-weld环境中并行执行的内容,因此我的方法一定有问题。
解决这种情况的正确方法是什么?
编辑:为了更清楚我尝试了什么…
public class DataCollector implements ISumRequest<Integer, Integer, String, FutureResult> {
ExecutorService pool = Executors.newCachedThreadPool();
@Inject
SessionBean sessionBean;
public Future<FutureResult> collectInformation(Integer snr, Integer pfnr, String requestType) {
CollectWorker worker = new CollectWorker (snr,pfnr,requestType,sessionBean.getUserName());
return pool.submit(worker);
}
}
您可以将您创建的worker封装在CDI创建上下文中,如下所示:
@Inject
private BeanManager beanManager;
public <T extends Object> T performInjection(final T obj) {
if (this.beanManager != null) { // only do injection if the bean manager is present.
// Create a creational context from the BeanManager
final CreationalContext creationalContext = this.beanManager.createCreationalContext(null);
// Create an injection target with the Type of the instance we need to inject into
final InjectionTarget injectionTarget = this.beanManager.createInjectionTarget(this.beanManager.createAnnotatedType(obj.getClass()));
// Perform injection into the instance
injectionTarget.inject(obj, creationalContext);
// Call PostConstruct on instance
injectionTarget.postConstruct(obj);
}
return obj;
}