我们尝试将项目从servlet重构为vertx3.x。我们希望重用负责查询数据的DAO
层:
interace Adapter {
List<Feature> query(String layer);
}
class DataBaseAdapter implements Adapter {
}
class FileAdapter implements Adapter {
}
class HttpVertx extends AbstractVertx {
void start() {
HttpServer server = vertx.createHttpServer();
Router router = Router.router(vertx);
router.route().handler((h->{
List<Feature> r=new ArrayList();
String[] layers=getLayerFromRequest(h.request());
layers.forEach(l->{
h.vertx().executeBlocking(future->{
future.complete(getAdapter(l).query(l));
},false,res->{
List<Feature> data=res.result();
r.addAll(data);
//now how can I know that the loop have ended, and I can send the `r` to the client?
});
});
}));
server.requestHandler(router::accept).listen(8080);
}
Adapter getAdapter(String layer){
//return database or file adapter accordingly
return null;
}
}
如图所示,原始adapter
查询都是块操作,一旦我在循环中执行它们,我不知道它们何时完成。
此外,我不确定是否有必要使用DatabaseAdapter
重构vertx-jdbc
?如果是,我将不得不将Adapter
接口的方法签名更改为同步,但FileAdapter
不支持。{/ p>
什么是正确的重构解决方案?
答案 0 :(得分:1)
尝试将循环逻辑移动到executeBlocking
块并将处理程序类型更改为Handler<List<Feature>>
不,这并非绝对必要,因为在executeBlocking
中包装这些调用已经在与Verticle的工作池进行数据库交互的昂贵工作。
答案 1 :(得分:0)
首先,不要使用executeBlocking()
。它打破了Vert.x的整个想法
其次,我建议重写你的DAO以返回Future
。这将需要一些工作,但工作将非常简单。
在高层次上,它看起来应该是这样的:
// Use map(), as it returns value
List<Future> futures = layers.map((l) -> {
return getAdapter(l).query(l);
});
CompositeFuture.all(futures).setHandler((r) -> {
if (r.succeeded()) {
// Continue here
}
});