【发布时间】:2020-12-20 07:07:14
【问题描述】:
在我的请求处理程序中,如果传入的accountId 无法转换为有效的ObjectId,我想捕获错误并发回有意义的消息;但是,这样做会导致返回类型不兼容,我无法弄清楚如何实现这个非常简单的用例。
我的代码:
@GetMapping("/{accountId}")
public Mono<ResponseEntity<Account>> get(@PathVariable String accountId) {
log.debug(GETTING_DATA_FOR_ACCOUNT, accountId);
try {
ObjectId id = new ObjectId(accountId);
return repository.findById(id)
.map(ResponseEntity::ok)
.switchIfEmpty(Mono.just(ResponseEntity.notFound().build()));
} catch (IllegalArgumentException ex) {
log.error(MALFORMED_OBJECT_ID, accountId);
// TODO(marco): find a way to return the custom error message. This seems to be currently
// impossible with the Reactive API, as using body(message) changes the return type to
// be incompatible (and Mono<ResponseEntity<?>> does not seem to cut it).
return Mono.just(ResponseEntity.badRequest().build());
}
}
body(T body) 方法将返回的Mono 的类型更改为(假设只发送一个String)Mono<ResponseEntity<String>>;但是,将方法的返回类型更改为 Mono<ResponseEntity<?>> 也不起作用:
...
return Mono.just(ResponseEntity.badRequest().body(
MALFORMED_OBJECT_ID.replace("{}", accountId)));
因为它在另一个 return 语句上给出了“不兼容的类型”错误:
error: incompatible types: Mono<ResponseEntity<Account>> cannot be converted to Mono<ResponseEntity<?>>
.switchIfEmpty(Mono.just(ResponseEntity.notFound().build()));
显然,将方法的返回类型更改为 Mono<?> 会起作用,但随后的响应是 ResponseEntity 的序列化 JSON,这不是我想要的。
我也尝试过使用onErrorXxxx() 方法,但它们在这里也不起作用,因为转换错误甚至在计算通量之前就发生了,我只是得到一个“vanilla”400 错误和一条空消息。
我能想到解决此问题的唯一方法是将message 字段添加到我的Account 对象并返回该对象,但这确实是一个可怕的黑客攻击。
【问题讨论】:
-
您需要阅读响应式编程的基础知识。你不应该使用
try/catch,如果你想向客户端返回一个错误应该返回一个包含ResponseStatusException的Mono.error。我建议阅读 reactor 文档中的入门指南。 projectreactor.io/docs/core/release/reference/#getting-started
标签: java spring-webflux spring-reactive