如果Flux流数据具有错误状态,我该如何返回不同的ServerResponse

时间:2019-10-17 10:03:06

标签: spring-webflux

我正在使用WebFlux实现REST端点,并且在基本操作上没有任何问题,但是有一个我不知道如何管理的操作。 我想返回与事件对象相关的PriceMessage对象,因此,如果事件存在,则端点返回ServerResponse.ok(),但如果事件不存在,则应返回ServerResponse.notFound()。

在存储库层中,有以下方法,如果存在且带有eventId的事件,则返回表示代码的Mono,如果不存在,则返回Mono.empty():

@Override
public Mono<Integer> getSportsEventId(long eventId) {
  Optional<SourceEventDto> optionalSourceEvent =
    springJpaSourceEventRepository.findByEventId(eventId);

  Mono<Integer> result = Mono.empty();

  if (optionalSourceEvent.isPresent()) {
    result = Mono.just(new Integer(optionalSourceEvent.get().getSourceId()));
  }

  return result;
}

然后,服务层将返回一个Flux,如果未找到事件,则该Flux将设置错误,或者连接到Redis以获取与sportsEventId相关的价格:

@Override
public Flux<PriceMessage> getPrices(long eventId) {
  return
    // get the sportsEventId
    sourceEventRepository.getSportsEventId(eventId)
      // notify the event does not exist
      .switchIfEmpty(Mono.error(new IllegalStateException("Event " + eventId + " does not exist")))
      // get the related PriceEntity objects
      .flatMapMany(priceRepository::findBySporsEventId)
      // transform to PriceMessage
      .map(priceMessageFactory::from);
}

此代码已经过单元测试,并且还调试了它,以确保如果在流中设置了错误,则不会调用flatMapMany和map部件。

最后,在REST层中有以下代码,即快乐的路径:

public Mono<ServerResponse> getPricesByEventId(ServerRequest request) {
  String eventIdParam = request.pathVariable("eventId");

  // call the service layer
  Flux<PriceMessage> prices = priceService.getPrices(eventId);

  return
    ServerResponse.ok()
      .contentType(MediaType.APPLICATION_STREAM_JSON)
      .body(prices, PriceMessage.class);
}

这很好,但如果价格流包含错误,因为找不到事件,我不知道如何返回404错误,在主体中设置错误消息,如下所示:

ServerResponse.status(HttpStatus.NOT_FOUND)
  .contentType(MediaType.APPLICATION_JSON_UTF8)
  .syncBody(<error_message_from_flux>);

伪代码将是这样,但我无法将其转换为反应性:

if (!prices.isError()) then
  return
    ServerResponse.ok()
      .contentType(MediaType.APPLICATION_STREAM_JSON)
      .body(prices, PriceMessage.class);
else
  return
    ServerResponse.status(HttpStatus.NOT_FOUND)
     .contentType(MediaType.APPLICATION_JSON_UTF8)
     .syncBody(<error_message_from_flux>);
end

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

如果发生错误,可以使用onErrorResume创建错误响应。

 return priceService.getPrices(eventId).flatMap(prices -> ServerResponse.ok()
          .contentType(MediaType.APPLICATION_STREAM_JSON)
          .body(prices, PriceMessage.class))
       .onErrorResume(err -> ServerResponse.status(HttpStatus.NOT_FOUND).body({Your Error Body Here}).build());

答案 1 :(得分:0)

您可以在注册路线时使用选择来处理它。

@Bean
public RouterFunction<ServerResponse> route(PriceMessageHandler handler) {
  return RouterFunctions.route().GET("/",
      request -> ServerResponse.ok().body(handler.handle(request), PriceMessage.class))
      .onError(Exception.class, (e, a) -> ServerResponse.status(HttpStatus.NOT_FOUND).build())
      .build();
}

或者您可以在ServerResponse上使用onErrorResume

return ServerResponse.ok().body(priceService.getPrices(eventId), PriceMessage.class).onErrorResume((e) -> ServerResponse.notFound().build());

希望这会有所帮助。