在Spring Web Flux中捕获异常

时间:2018-10-18 15:41:09

标签: java spring exception spring-webflux

我有以下用于通过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);
        }
    }
}

但是我觉得或者有更好的方法,或者我试图实现的目标是错误的。正确的方法是什么?

1 个答案:

答案 0 :(得分:2)

您永远不要使用块。反应堆的目的是处理链中的所有东西。因此,您的方法应该返回一个Mono而不是对象本身。

如果要更改异常,则应使用.onErrorMap(throwable-> extractFromReactiveException(throwable)); 在bodyToMono之后。

并使提取方法返回HttpException而不是Mono。

这里是文档,寻找onErrorMap方法及其重载。 https://projectreactor.io/docs/core/release/api/

请随时询问您是否还有任何疑问!