Spring ResponseErrorHandler中ClientHttpResponse响应流为null问题排查
问题原因与解决方案
为什么流会是null?
Spring的RestTemplate默认逻辑中,当响应状态码是2xx时,会优先调用消息转换器读取响应体进行反序列化(比如转成目标DTO对象),这个过程中流会被读取并关闭。等你在hasError()方法里再调用httpResponse.getBody()时,流已经被消费完毕,自然返回null。
而且ResponseErrorHandler的设计初衷是处理状态码层面的错误(4xx/5xx),并非用来处理2xx成功响应里的业务错误,所以Spring不会为2xx响应保留流给ErrorHandler读取。
解决办法
方案1:在正常响应流程中检查业务错误(推荐)
不要用ResponseErrorHandler处理2xx里的错误,直接在获取响应后解析Body判断:
// 初始化RestTemplate RestTemplate restTemplate = new RestTemplate(); // 发起请求获取响应实体 ResponseEntity<YourBizResponse> responseEntity = restTemplate.exchange( "外部API地址", HttpMethod.POST, new HttpEntity<>(yourRequest), YourBizResponse.class ); YourBizResponse bizResponse = responseEntity.getBody(); // 检查业务错误标识 if (bizResponse != null && bizResponse.hasError()) { // 抛出业务异常或处理错误逻辑 throw new RuntimeException("业务错误:" + bizResponse.getErrorMsg()); }
方案2:让响应流可重复读取(适合一定要用ErrorHandler的场景)
给RestTemplate配置BufferedClientHttpRequestFactory,它会把响应体缓存到内存中,让流可以被多次读取:
// 配置RestTemplate使用缓冲请求工厂 RestTemplate restTemplate = new RestTemplate(); restTemplate.setRequestFactory(new BufferedClientHttpRequestFactory(new SimpleClientHttpRequestFactory())); // 绑定自定义ErrorHandler restTemplate.setErrorHandler(new RestTemplateResponseErrorHandler());
之后在hasError()方法里调用httpResponse.getBody()就能拿到可读取的流,不会再返回null。
内容的提问来源于stack exchange,提问作者D.T
相关产品推荐
相关产品推荐

