0

我已将 Micronaut 应用程序从 2.5.XX 更新到 3.0.0。根据 Micronaut 文档,项目 reactor 是推荐用于响应式编程的响应式库。

@Controller("/product")
public class ProductController implements IProductOperation {
    @Override
    public Flux<List> freeTextSearch(String text) {
        return iProductManager.findFreeText(text).onErrorResume(throwable -> {
            return Flux.error(new GlobalException(throwable));
        });
    }
}

public interface IProductOperation {
    @Get(value = "/search/{text}")
    Flux<?> freeTextSearch(@NotBlank String text);
}

当我卷曲终点时curl -X 'GET' 'http://localhost:8081/product/search/ffff' -H 'accept: application/json',它会走向无限。

由于我在系统上有错误,所以 returnFlux.error(new GlobalException(throwable));应该返回 500 内部系统错误,但是,它进入了无限

我已经集成了rabbitMQ,并且rabbitMQ 生产者已关闭。iProductManager.findFreeText(text)由于 rabbitMQ 生产者未运行,因此引发异常。它应该抛出一个异常并且应该调用全局错误处理,而不是无限。但是没有按预期工作

public class GlobalException extends RuntimeException{
    public GlobalException(Throwable throwable){super(throwable);}
}

此方法永远不会因错误而被调用。

@Produces
@Singleton
@Requires(classes = {GlobalException.class, ExceptionHandler.class})
public class GlobalExceptionHandler implements ExceptionHandler<GlobalException, HttpResponse> {
    private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @Override
    public HttpResponse handle(HttpRequest request, GlobalException exception) {
        LOG.error(exception.getLocalizedMessage());
        LOG.error(exception.getCause().getMessage());
        Arrays.stream(exception.getStackTrace()).forEach(item -> LOG.error(item.toString()));
        return HttpResponse.serverError(exception.getLocalizedMessage());
    }
}

日志

22:40:02.151 [default-nioEventLoopGroup-1-3] INFO  reactor.Flux.OnErrorResume.1 - onSubscribe(FluxOnErrorResume.ResumeSubscriber)
22:40:02.176 [default-nioEventLoopGroup-1-3] INFO  reactor.Flux.OnErrorResume.1 - request(1)
4

1 回答 1

0

我认为您使用了错误的反应器Flux运算符:

  • onErrorResume发生错误时切换到不同Flux的位置;您可以将其视为“后备通量”。在您的情况下,回退会引发错误 - 这可以解释无限循环。
  • onErrorMap应该做你正在寻找的:将一个异常映射到另一个可用于 HTTP 响应的异常

如果您想包装该 Flux 中的所有异常,您可以执行以下操作:

return iProductManager.findFreeText(text)
        .onErrorMap(throwable -> new GlobalException(throwable));

请注意,其他onErrorMap方法允许您拥有更细粒度的行为。

于 2021-08-26T12:27:54.670 回答