使用 Mono 流程处理异常
Handling exception with Mono flow
我有一个如下所示的 WebFlux 处理程序。
@Transactional
public Mono<ServerResponse> submitOrder(final ServerRequest request) {
return context.retrieveUser().flatMap(usr -> {
try {
return Mono.zip(branchSetting, labOrderDetail, labOrderTests).flatMap(response -> {
final Mono<String> submitOrderMono = service.submitOrder(usr);
final Mono<Integer> updateStatusMono = orderRepository.updateStatus(orderId);
return Mono.zip(submitOrderMono, updateStatusMono).flatMap(submitResponse -> {
return ok().bodyValue(submitResponse.getT1());
}).onErrorResume(e -> {
if (e instanceof ServiceException) {
ServiceException ex = (ServiceException) e;
return status(ex.getStatusCode()).bodyValue(e.getMessage());
} else {
return status(500).bodyValue(e.getMessage());
}
});
});
} catch (Throwable e) {
if (e instanceof ServiceException) {
ServiceException ex = (ServiceException) e;
return status(ex.getStatusCode()).bodyValue(e.getMessage());
} else {
return status(500).bodyValue(e.getMessage());
}
}
});
}
来自服务 class、
的 submitOrder 方法
public Mono<String> submitOrder(final Order order,
if (order.getPatientId() != null) {
throw new ServiceException("Missing Id for patient !!!", HttpStatus.BAD_REQUEST.value());
}
}
在这里,我正在做一些验证并抛出异常。
但是,此异常不会进入调用 main 方法中的 onErrorResume 或 catch 块,因此服务调用者会看到 500 错误。
不确定这里有什么问题。
在反应式 WebFlux 上下文中工作时,抛出异常并使用 try-catch-block 恕我直言,这并不是最佳实践。
更惯用的方法是使用 Mono.error()
而不是 throw
命令。 Mono.error()
发出一个错误信号,以便随后的 onErrorResume()
可以处理它。
也就是说,submitOrder()
可能看起来像这样:
public Mono<String> submitOrder(final Order order) {
if (order.getPatientId() == null) {
Mono.error(new ServiceException("Missing Id for patient !!!", 500));
}
return Mono.just("some reasonable result");
}
通过这次重写,第一个片段应该(可能有一些小的调整)以这种方式工作:
public Mono<ServerResponse> submitOrder(final ServerRequest request) {
return context.retrieveUser().flatMap(usr -> {
return Mono.zip(branchSetting, labOrderDetail, labOrderTests).flatMap(response -> {
final Mono<String> submitOrderMono = service.submitOrder(usr);
final Mono<Integer> updateStatusMono = orderRepository.updateStatus(orderId);
return Mono.zip(submitOrderMono, updateStatusMono).flatMap(submitResponse -> {
return ok().bodyValue(submitResponse.getT1());
}).onErrorResume(e -> {
if (e instanceof ServiceException) {
ServiceException ex = (ServiceException) e;
return status(ex.getStatusCode()).bodyValue(e.getMessage());
} else {
return status(500).bodyValue(e.getMessage());
}
});
});
});
}
我有一个如下所示的 WebFlux 处理程序。
@Transactional
public Mono<ServerResponse> submitOrder(final ServerRequest request) {
return context.retrieveUser().flatMap(usr -> {
try {
return Mono.zip(branchSetting, labOrderDetail, labOrderTests).flatMap(response -> {
final Mono<String> submitOrderMono = service.submitOrder(usr);
final Mono<Integer> updateStatusMono = orderRepository.updateStatus(orderId);
return Mono.zip(submitOrderMono, updateStatusMono).flatMap(submitResponse -> {
return ok().bodyValue(submitResponse.getT1());
}).onErrorResume(e -> {
if (e instanceof ServiceException) {
ServiceException ex = (ServiceException) e;
return status(ex.getStatusCode()).bodyValue(e.getMessage());
} else {
return status(500).bodyValue(e.getMessage());
}
});
});
} catch (Throwable e) {
if (e instanceof ServiceException) {
ServiceException ex = (ServiceException) e;
return status(ex.getStatusCode()).bodyValue(e.getMessage());
} else {
return status(500).bodyValue(e.getMessage());
}
}
});
}
来自服务 class、
的 submitOrder 方法public Mono<String> submitOrder(final Order order,
if (order.getPatientId() != null) {
throw new ServiceException("Missing Id for patient !!!", HttpStatus.BAD_REQUEST.value());
}
}
在这里,我正在做一些验证并抛出异常。
但是,此异常不会进入调用 main 方法中的 onErrorResume 或 catch 块,因此服务调用者会看到 500 错误。
不确定这里有什么问题。
在反应式 WebFlux 上下文中工作时,抛出异常并使用 try-catch-block 恕我直言,这并不是最佳实践。
更惯用的方法是使用 Mono.error()
而不是 throw
命令。 Mono.error()
发出一个错误信号,以便随后的 onErrorResume()
可以处理它。
也就是说,submitOrder()
可能看起来像这样:
public Mono<String> submitOrder(final Order order) {
if (order.getPatientId() == null) {
Mono.error(new ServiceException("Missing Id for patient !!!", 500));
}
return Mono.just("some reasonable result");
}
通过这次重写,第一个片段应该(可能有一些小的调整)以这种方式工作:
public Mono<ServerResponse> submitOrder(final ServerRequest request) {
return context.retrieveUser().flatMap(usr -> {
return Mono.zip(branchSetting, labOrderDetail, labOrderTests).flatMap(response -> {
final Mono<String> submitOrderMono = service.submitOrder(usr);
final Mono<Integer> updateStatusMono = orderRepository.updateStatus(orderId);
return Mono.zip(submitOrderMono, updateStatusMono).flatMap(submitResponse -> {
return ok().bodyValue(submitResponse.getT1());
}).onErrorResume(e -> {
if (e instanceof ServiceException) {
ServiceException ex = (ServiceException) e;
return status(ex.getStatusCode()).bodyValue(e.getMessage());
} else {
return status(500).bodyValue(e.getMessage());
}
});
});
});
}