我有以下用于通过Web服务调用耗时的操作的类:
@Service
public class InferenceService {
@Autowired
private final WebClient inferenceClient;
public ByteArrayResource invoke(FileSystemResource resource) throws HttpException {
Mono<ByteArrayResource> mono = inferenceClient
.post()
.uri(INFERENCE_URI)
.contentType(MediaType.valueOf("application/zip"))
.body(BodyInserters.fromResource(resource))
.accept()
.retrieve()
.bodyToMono(ByteArrayResource.class);
ByteArrayResource zip = mono.block();
return zip;
}
}
如果在Web服务调用期间发生异常(如UnknownHostException),则将其包装在ReactiveException中。我希望我的类捕获原始异常并将其作为HttpException重新抛出,以便能够对其进行记录,由Spring异常处理程序处理,从我的控制器返回500状态并且不难理解带有抑制异常的stacktrace在我的日志中。我写了这样的东西:
@Service
public class InferenceService {
@Autowired
private final WebClient inferenceClient;
public ByteArrayResource invoke(FileSystemResource resource) throws HttpException {
Mono<ByteArrayResource> mono = inferenceClient
.post()
.uri(INFERENCE_URI)
.contentType(MediaType.valueOf("application/zip"))
.body(BodyInserters.fromResource(resource))
.accept()
.retrieve()
.onStatus(HttpStatus::is5xxServerError, this::getStatus500Error)
.bodyToMono(ByteArrayResource.class);
try {
ByteArrayResource zip = mono.block();
return zip;
} catch (RuntimeException e) {
throw extractFromReactiveException(e);
}
}
private Mono<? extends Throwable> getStatus500Error(ClientResponse clientResponse) {
return Mono.error(new InternalServerError(getStatusErrorMsg(clientResponse)));
}
private HttpException extractFromReactiveException(RuntimeException e) {
if (e.getCause() instanceof HttpException) {
return (HttpException) e.getCause();
} else {
return new InternalServerError(e);
}
}
}
但是我觉得或者有更好的方法,或者我试图实现的目标是错误的。正确的方法是什么?
答案 0 :(得分:2)
您永远不要使用块。反应堆的目的是处理链中的所有东西。因此,您的方法应该返回一个Mono而不是对象本身。
如果要更改异常,则应使用.onErrorMap(throwable-> extractFromReactiveException(throwable)); 在bodyToMono之后。
并使提取方法返回HttpException而不是Mono。
这里是文档,寻找onErrorMap方法及其重载。 https://projectreactor.io/docs/core/release/api/
请随时询问您是否还有任何疑问!