前言
spring cloud 對feign調用對返回值做了包裝處理,通過一些列Decoder來處理feign訪問的返回值。
具體流程 從SynchronousMethodHandler中的decoder開始會經歷如下幾個decoder:
OptionalDecoder -> ResponseEntityDecoder -> SpringDecoder
可以在 FeignClientsConfiguration 看到有對上面三個decoder的定義,有興趣的可以自行閱讀源碼。
feign返回值攔截 + response只能讀取一次處理
feign返回值攔截只需要自定義一個coder,替換 FeignClientsConfiguration 中的 decoder定義即可,具體代碼如下:
配置自定義decoder:
/**
* feign返回值攔截
* @author liufei
*/
public final class ResultStatusDecoder implements Decoder {
public static final String CONTENT_KEY = "content";
final Decoder delegate;
public ResultStatusDecoder(Decoder delegate) {
Objects.requireNonNull(delegate, "Decoder must not be null. ");
this.delegate = delegate;
}
@Override
public Object decode(Response response, Type type) throws IOException {
// 判斷是否返回參數是否是異常
String resultStr = IOUtils.toString(response.body().asInputStream(), StandardCharsets.UTF_8);
// 拿到返回值,進行自定義邏輯處理
log.info("do business ,result msg ->{}",resultStr);
// 回寫body,因爲response的流數據只能讀一次,這裏回寫後重新生成response
return delegate.decode(response.toBuilder().body(resultStr, StandardCharsets.UTF_8).build(), type);
}
}
由於response中的body只能讀取一次,所以最後需要把body回寫,再重新生成response傳遞到下一個decoder
配置自定義bean:
@Configuration
public class SupportAutoConfiguration {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
public Decoder feignDecoder() {
return new ResultStatusDecoder(new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(this.messageConverters))));
}
}