【问题标题】:Map Error using onErrorMap in WebFlux for Mono<Void>在 WebFlux for Mono<Void> 中使用 onErrorMap 映射错误
【发布时间】:2019-09-19 21:52:30
【问题描述】:

我有两个微服务,让我们说一个前端和后端,对于前端,我使用 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&lt;Void&gt;

@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怎么用?

【问题讨论】:

    标签: spring-boot spring-webflux


    【解决方案1】:

    此错误与运算符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);
                    });
    
        }
    

    最后,我建议不要在反应式管道中使用阻塞调用,除非你真的必须这样做。 (更喜欢 WebClient 或其他非阻塞 HTTP 客户端而不是阻塞客户端作为 feign)。

    【讨论】:

    • 感谢您提供有关阻塞调用的信息,创建线程不是一种选择,将与阻塞客户端 feign 一起使用,因为我使用功能区自定义负载均衡器,希望使用响应式 feign。
    • 反应性伪装在这里可用:github.com/Playtika/feign-reactive。但它只是对 webclient 的抽象。如果该方法仍然对您不起作用,请在反应器链中使用 pubslishOn(Schedulers.boundedElastic()) 将工作委派给不同的线程。这不会阻塞反应器线程。
    猜你喜欢
    • 2021-11-09
    • 2018-06-05
    • 2021-12-17
    • 2021-05-08
    • 2020-10-08
    • 2021-06-17
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多