Openfeign ErrorDecoder 导致 java.io.IOException: 流已关闭

bjw*_*zds 3 java stream feign openfeign

当我尝试实现ErrorDecoder解码 feign 异常时,我发现输入的流response.body()已关闭,因此当我尝试读取流并转换为字符串时,它抛出java.io.IOException: stream is closed. 真的很困惑,因为在解码器之前,我没有做任何事情来关闭流。

public class FeignClientErrorDecoder implements ErrorDecoder {
    @Override
    public Exception decode(String methodKey, Response response) {
        log.info("feign client response: {}", response);
        String body = null;
        try {
            body = Util.toString(response.body().asReader(Charset.defaultCharset()));
        } catch (IOException e) {
            log.error("feign.IOException", e);
        }
        return new ServiceException(MessageCode.builder(ExceptionCodeEnum.ERROR));
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 9

我经历了这个噩梦,这都是 IDE 的错。

调试模式中的断点在response.body().asReader导致流关闭之前/结束。

阅读正文后简单地开始调试,一切顺利。

  • 你值得一枚奖牌 (5认同)
  • 伙计,你节省了我很多时间!非常感谢!!!! (3认同)

Udh*_*ran 7

Logger / System.out.println / IDE 调试模式

在获得之前请勿使用上述任何功能response.body()

如果您使用上述任何功能来打印/记录/查看您的response对象,那么它将response.body()在内部处理并关闭InputStream. 所以在这种情况下你会得到Stream is closed错误。

要解决此问题,请在response.body()记录器之前进行处理。现在您可以通过运行应用程序来检查这一点,但不能在调试模式下运行。

示例代码:

@Override
  public Exception decode(final String methodKey, final Response response) {
    final String error = getResponseBodyAsString(response.body());
    LOGGER.error("{} failed with response {}", methodKey, response);
    return new ServiceException("Request failed with status: " + response.status()
                                                         + " and error: " + error);
  }

  private String getResponseBodyAsString(final Response.Body body) {
    try {
      return IOUtils.toString(body.asReader(StandardCharsets.UTF_8));
    } catch (final IOException e) {
      LOGGER.error("Failed to read the response body with error: ", e);
    }
    return null;
  }
Run Code Online (Sandbox Code Playgroud)

注意:如果您处于调试模式,那么您的 IDEA 将处理此响应,因此即使在这种情况下您也会收到相同的错误。所以请不要在调试模式下检查此项。