|
|
@@ -0,0 +1,84 @@
|
|
|
+package com.usky.demo.feign;
|
|
|
+
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.fasterxml.jackson.databind.type.CollectionType;
|
|
|
+import com.usky.common.core.bean.ApiResult;
|
|
|
+import com.usky.demo.domain.HistorysInnerResultVO;
|
|
|
+import com.usky.demo.domain.LastInnerResultVO;
|
|
|
+import feign.Response;
|
|
|
+import feign.Util;
|
|
|
+import feign.codec.Decoder;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.lang.reflect.ParameterizedType;
|
|
|
+import java.lang.reflect.Type;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Optional;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 兼容 TSDB 两种响应:裸 JSON 数组(旧实现)与 {@link ApiResult} 包装(新实现)。
|
|
|
+ */
|
|
|
+public class TsdbProxyApiResultFeignDecoder implements Decoder {
|
|
|
+
|
|
|
+ private final Decoder delegate;
|
|
|
+ private final ObjectMapper objectMapper;
|
|
|
+
|
|
|
+ public TsdbProxyApiResultFeignDecoder(Decoder delegate, ObjectMapper objectMapper) {
|
|
|
+ this.delegate = delegate;
|
|
|
+ this.objectMapper = objectMapper;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Object decode(Response response, Type type) throws IOException {
|
|
|
+ if (response.body() == null) {
|
|
|
+ return delegate.decode(response, type);
|
|
|
+ }
|
|
|
+ byte[] bodyData = Util.toByteArray(response.body().asInputStream());
|
|
|
+ String trimmed = new String(bodyData, StandardCharsets.UTF_8).trim();
|
|
|
+ if (trimmed.startsWith("[")) {
|
|
|
+ Optional<Object> wrapped = wrapJsonArrayAsApiResult(bodyData, type);
|
|
|
+ if (wrapped.isPresent()) {
|
|
|
+ return wrapped.get();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Response rebuilt = Response.builder()
|
|
|
+ .status(response.status())
|
|
|
+ .reason(response.reason())
|
|
|
+ .headers(response.headers())
|
|
|
+ .request(response.request())
|
|
|
+ .body(bodyData)
|
|
|
+ .build();
|
|
|
+ return delegate.decode(rebuilt, type);
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ private Optional<Object> wrapJsonArrayAsApiResult(byte[] bodyData, Type type) throws IOException {
|
|
|
+ if (!(type instanceof ParameterizedType)) {
|
|
|
+ return Optional.empty();
|
|
|
+ }
|
|
|
+ ParameterizedType pt = (ParameterizedType) type;
|
|
|
+ if (!ApiResult.class.isAssignableFrom((Class<?>) pt.getRawType())) {
|
|
|
+ return Optional.empty();
|
|
|
+ }
|
|
|
+ Type dataType = pt.getActualTypeArguments()[0];
|
|
|
+ if (!(dataType instanceof ParameterizedType)) {
|
|
|
+ return Optional.empty();
|
|
|
+ }
|
|
|
+ ParameterizedType listPt = (ParameterizedType) dataType;
|
|
|
+ if (!List.class.isAssignableFrom((Class<?>) listPt.getRawType())) {
|
|
|
+ return Optional.empty();
|
|
|
+ }
|
|
|
+ Type elemType = listPt.getActualTypeArguments()[0];
|
|
|
+ if (!(elemType instanceof Class)) {
|
|
|
+ return Optional.empty();
|
|
|
+ }
|
|
|
+ Class<?> elemClass = (Class<?>) elemType;
|
|
|
+ if (elemClass != LastInnerResultVO.class && elemClass != HistorysInnerResultVO.class) {
|
|
|
+ return Optional.empty();
|
|
|
+ }
|
|
|
+ CollectionType listJavaType = objectMapper.getTypeFactory().constructCollectionType(List.class, elemClass);
|
|
|
+ List<?> list = objectMapper.readValue(bodyData, listJavaType);
|
|
|
+ return Optional.of(ApiResult.success((List) list));
|
|
|
+ }
|
|
|
+}
|