Quarkus 中的 Vertx Web 路由和反应式 Pg 客户端问题



应用程序基于以下堆栈:

  • 夸库斯 1.5.0
  • 扩展:vertx-web,reactive-pgclient

完整的代码在这里。

我通过@Observes Router创建了一个路由器。

@ApplicationScoped
public class RoutesObserver {
@Inject PostsHandlers handlers;
public void route(@Observes Router router) {
router.get("/posts").produces("application/json").handler(handlers::getAll);
router.post("/posts").consumes("application/json").handler(handlers::save);
router.get("/posts/:id").produces("application/json").handler(handlers::get);
router.put("/posts/:id").consumes("application/json").handler(handlers::update);
router.delete("/posts/:id").handler(handlers::delete);
router.get("/hello").handler(rc -> rc.response().end("Hello from my route"));
}
}

并将处理程序提取到一个独立的 bean 中。

@ApplicationScoped
class PostsHandlers {
private static final Logger LOGGER = Logger.getLogger(PostsHandlers.class.getSimpleName());
PostRepository posts;
ObjectMapper objectMapper;
@Inject
public PostsHandlers(PostRepository posts, ObjectMapper objectMapper) {
this.posts = posts;
this.objectMapper = objectMapper;
}
public void getAll(RoutingContext rc) {
this.posts.findAll().thenAccept(
data -> rc.response()
.write(toJson(data))
.end()
);
}
//... other methods.
}

PostRepository使用了Java 8CompletionStageAPI。

@ApplicationScoped
public class PostRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(PostRepository.class);
private final PgPool client;
@Inject
public PostRepository(PgPool _client) {
this.client = _client;
}
public CompletionStage<List<Post>> findAll() {
return client.query("SELECT * FROM posts ORDER BY id ASC")
.execute()
.thenApply(rs -> StreamSupport.stream(rs.spliterator(), false)
.map(this::from)
.collect(Collectors.toList())
);
}

当我运行此应用程序并尝试访问/posts时。它被冻结,不打印任何响应。

使用write方法时,需要(事先(设置content-length标头。

有几种方法可以解决此问题:

  1. 您可以使用.end(toJson(data))代替write(...).end()- 它会自动计算长度
  2. 您可以使用.putHeader("transfer-encoding", "chunked")write(...).end()- 如果您打算检索多个结果,这很有趣,因为它将每个块一个接一个地写入客户端,避免一次性发送大量有效负载
  3. 您可以将content-length设置为:
String result = toJson(data);
rc.response()
.putHeader("content-length", Long.toString(result.length()))
.write(result)
.end();

最新更新