如何使用 FeignErrorDecoder 摆脱 stream is closed 错误?
How to get rid of stream is closed error with FeignErrorDecoder?
我有一个这样构建的虚拟客户端服务:
Feign.Builder builder = Feign.builder()
.contract(new SpringMvcContract())
.encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
.errorDecoder(new FeignClientErrorHandler())
return builder.target(targetClass, url);
我有 FeignClientErrorDecoder
,看起来像这样:
public class FeignClientErrorDecoder implements ErrorDecoder {
private static final ObjectMapper MAPPER = new ObjectMapper().registerModule(new JavaTimeModule());
@Override
public Exception decode(final String methodKey,
final Response response) {
try {
byte[] body = Util.toByteArray(response.body().asInputStream());
ApiError apiError = MAPPER.readValue(body, ApiError.class);
return ExceptionFactory.createFrom(apiError);
} catch (IOException | ApiErrorException e) {
return new TechnicalClientException("Could not extract error payload.", e);
}
}
}
无论我选择哪种读取输入流解决方案,我总是会收到 stream is closed
错误。
我错过了什么?谁在关闭它?任何解决方法?
完整代码在这里:
https://github.com/louisamoros/feign-error-code
您可以 运行 mvn clean install
并查看 1 个测试错误。
感谢您提供完整代码。由于在错误解码器中记录 response
而发生错误:
LOGGER.error("Feign client error handler. Method: {}, Response: {}", methodKey, response);
这里,toString()
在响应中被调用,包括它的正文。因此,响应主体的输入流被读取并在那里关闭,以后无法再次读取。
您可以从日志记录中删除 response
或复制其输入流(通过 apache IOUtils 或类似的东西),然后使用其副本。在这种情况下,映射器将成功解析所有内容并到达下一行 return new ApiException()
。
顺便说一下,调试这种代码要小心。现代 IDE(例如 IntelliJ IDEA)可以在默认到达断点时对范围内的所有对象调用 toString()
,因此同样的问题也会因此而发生。在这里,您可以安全地将断点仅放在 MAPPER.readValue
行之后。
我有一个这样构建的虚拟客户端服务:
Feign.Builder builder = Feign.builder()
.contract(new SpringMvcContract())
.encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
.errorDecoder(new FeignClientErrorHandler())
return builder.target(targetClass, url);
我有 FeignClientErrorDecoder
,看起来像这样:
public class FeignClientErrorDecoder implements ErrorDecoder {
private static final ObjectMapper MAPPER = new ObjectMapper().registerModule(new JavaTimeModule());
@Override
public Exception decode(final String methodKey,
final Response response) {
try {
byte[] body = Util.toByteArray(response.body().asInputStream());
ApiError apiError = MAPPER.readValue(body, ApiError.class);
return ExceptionFactory.createFrom(apiError);
} catch (IOException | ApiErrorException e) {
return new TechnicalClientException("Could not extract error payload.", e);
}
}
}
无论我选择哪种读取输入流解决方案,我总是会收到 stream is closed
错误。
我错过了什么?谁在关闭它?任何解决方法?
完整代码在这里:
https://github.com/louisamoros/feign-error-code
您可以 运行 mvn clean install
并查看 1 个测试错误。
感谢您提供完整代码。由于在错误解码器中记录 response
而发生错误:
LOGGER.error("Feign client error handler. Method: {}, Response: {}", methodKey, response);
这里,toString()
在响应中被调用,包括它的正文。因此,响应主体的输入流被读取并在那里关闭,以后无法再次读取。
您可以从日志记录中删除 response
或复制其输入流(通过 apache IOUtils 或类似的东西),然后使用其副本。在这种情况下,映射器将成功解析所有内容并到达下一行 return new ApiException()
。
顺便说一下,调试这种代码要小心。现代 IDE(例如 IntelliJ IDEA)可以在默认到达断点时对范围内的所有对象调用 toString()
,因此同样的问题也会因此而发生。在这里,您可以安全地将断点仅放在 MAPPER.readValue
行之后。