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

9
当我尝试实现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));
    }
}
2个回答

23

我曾经历过这个噩梦,而这完全是IDE的错。

在调试模式下,断点位于response.body().asReader之前/之上,导致流关闭。

只需在读取完Body后开始调试,一切就会顺利进行。


3
人啊,你帮我省了好多时间!!!非常感谢!!! - DanielSP
5
你应该得到一枚奖章。 - Drunken Daddy
兄弟,你真的应该得到一枚奖章。 - Habib Ali
谢谢!真希望我一个月前就知道这个。 - Tsonglew

7

日志记录器 / 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;
  }

注意:如果您正在调试模式下,则IDEA将处理此响应,因此即使在这种情况下,您仍将收到相同的错误。因此,请勿在调试模式下进行此检查。

这个答案比上面的解决方案更正确,因为它现在指出了问题所在,并提出了一个连贯的代码解决方案。 - Antonio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接