spring-boot - 在 Mono<Void> 的 WebFlux 中使用 onErrorMap 时发生映射错误

标签 spring-boot spring-webflux

我有两个微服务,让我们说一个前端和后端,对于前端,我使用 WebFlux 并使用 feign 客户端调用后端服务,如下面的代码示例所示,虽然下面的代码示例有效,但我想要使用 Function 的通用异常处理程序并提供给 onErrorMap

@RestController
@Slf4j
public class MyFrentEndService {

    @Autowired
    private MyBackEndService client;

    @PostMapping(value="/hello", consumes="application/json")
    public Mono<Void> sayHello(@Valid String msg) {
        log.info("Message is {}", msg);
        return Mono.create(sink-> {
            try {
                client.hello(msg);
            }catch (FeignException e) {
                System.out.println(e.status());
                HttpStatus status = e.status() ==0 ? HttpStatus.SERVICE_UNAVAILABLE : HttpStatus.valueOf(e.status());
                String message = e.getMessage();
                sink.error(new ResponseStatusException(status, message));
            }
            sink.success();
        });

    }

}

尝试使用onErrorMap ,但出现编译错误,请使用 Mono 而不是 Mono<Void>

@RestController
@Slf4j
public class MyFrentEndService {

    @Autowired
    private MyBackEndService client;

    @PostMapping(value="/hello", consumes="application/json")
    public Mono<Void> sayHello(@Valid String msg) {
        log.info("Message is {}", msg);
        return Mono.fromSupplier(() -> {
                  client.hello(msg);
                  return null;
               }).onErrorMap(e->{
                     HttpStatus status = e.status() ==0 } HttpStatus.SERVICE_UNAVAILABLE : HttpStatus.valueOf(e.status());
                     String message = e.getMessage();
                     return new ResponseStatusException(status, message);
                });

    }

}

如何使用onErrorMap

最佳答案

此错误与运算符onErrorMap无关。此代码无法编译,因为编译器无法将 Mono.fromSupplier 方法返回的泛型类型推断为 Void - 您在提供的函数上返回 null。 应通过执行以下操作来纠正此问题:

    @PostMapping(value="/hello", consumes="application/json")
    public Mono<Void> sayHello(@Valid String msg) {
        log.info("Message is {}", msg);
        return Mono.<Void>fromSupplier(() -> {
                  client.hello(msg);
                  return null;
               }).onErrorMap(e->{
                     HttpStatus status = e.status() ==0 ? HttpStatus.SERVICE_UNAVAILABLE : HttpStatus.valueOf(e.status());
                     String message = e.getMessage();
                     return new ResponseStatusException(status, message);
                });

    }

我认为执行以下操作更为惯用:

    @PostMapping(value="/hello", consumes="application/json")
    public Mono<Void> sayHello(@Valid String msg) {
        log.info("Message is {}", msg);
        return Mono.fromRunnable(() -> {
                  client.hello(msg);
               })
               .then()
               .onErrorMap(e->{
                     HttpStatus status = e.status() ==0 ? HttpStatus.SERVICE_UNAVAILABLE : HttpStatus.valueOf(e.status());
                     String message = e.getMessage();
                     return new ResponseStatusException(status, message);
                });

    }

最后,我建议不要在响应式(Reactive)管道内使用阻塞调用,除非确实有必要。 (首选 WebClient 或其他非阻塞 HTTP 客户端,而不是阻塞客户端作为 feign)。

关于spring-boot - 在 Mono<Void> 的 WebFlux 中使用 onErrorMap 时发生映射错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55934420/

相关文章:

java - 如何使用 @Valid List 的 BindingResult 获取错误列表

java - 如何在Spring Security中实现基于JWT的认证和授权

java - PubSubInboundChannelAdapter 在收到第四条消息后停止接收消息

spring-boot - openapi 3.0 中所有 API 的强制 header

java - 如何在Reactor中进行分页?

java - 使用 Spring Boot 配置 Ehcache TTL 超时

java - 处理程序调度失败;嵌套的异常是java.lang.NoSuchMethodError:io.netty.handler.ssl.SslProvider.isAlpnSupported

Spring WebFlux 检测客户端断开连接

spring-webflux - 使用 spring 响应式(Reactive) webClient 面临问题 "WebClientRequestException: Pending acquire queue has reached its maximum size of 1000"

java - onErrorResume 运算符会忽略 flatMap 中抛出的异常