Quarkus 中的 Vertx Web 路由和 Reactive Pg Client 问题
Vertx web routes and Reactive Pg Client issue in Quarkus
该应用程序基于以下堆栈:
- Quarkus 1.5.0
- 扩展:vertx-web、reactive-pgclient
完整代码为here.
我通过 @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 8 CompletionStage
API.
@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
header.
有几种方法可以解决这个问题:
- 您可以使用
.end(toJson(data))
而不是 write(...).end()
- 它会自动计算长度
- 您可以使用
.putHeader("transfer-encoding", "chunked")
和 write(...).end()
- 如果您计划检索多个结果,这很有趣,因为它将每个块一个一个地写入客户端,避免一次发送大量有效负载去
- 您可以将
content-length
设置为:
String result = toJson(data);
rc.response()
.putHeader("content-length", Long.toString(result.length()))
.write(result)
.end();
该应用程序基于以下堆栈:
- Quarkus 1.5.0
- 扩展:vertx-web、reactive-pgclient
完整代码为here.
我通过 @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 8 CompletionStage
API.
@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
header.
有几种方法可以解决这个问题:
- 您可以使用
.end(toJson(data))
而不是write(...).end()
- 它会自动计算长度 - 您可以使用
.putHeader("transfer-encoding", "chunked")
和write(...).end()
- 如果您计划检索多个结果,这很有趣,因为它将每个块一个一个地写入客户端,避免一次发送大量有效负载去 - 您可以将
content-length
设置为:
String result = toJson(data);
rc.response()
.putHeader("content-length", Long.toString(result.length()))
.write(result)
.end();