openfeign 调用的时候如何去除统一响应封装

2021-11-23 15:37:31 +08:00
 Geekerstar

目前用 @RestControllerAdvice 封装了统一响应,包上了 success 、code 等统一响应。

A 服务通过 feign 调用 B 服务后获取的结果中,也包上了这个响应,如何统一的去除通过 feign 调用而包装的统一响应呢?让获取到的结果可以直接使用

2944 次点击
所在节点    Java
12 条回复
devswork
2021-11-23 15:51:08 +08:00
写个解析 tool 类不就行了,顺便还能 check 一下 code
xwayway
2021-11-23 16:01:49 +08:00
当初让你卷八股文你不肯,现在游泳了吧。来来来,设计模式来一波,今天你用 openfeigin ,明天用纯 httpclient ,后天用 resttemplate 。这个时候应该加上一个中介者,来减少具体调用执行层和调用方之间的耦合,同时可以将 success ,code 这些统一格式的解析放到这个中介者里面来,中介者返回给调用方的就是纯纯的业务对象
securityCoding
2021-11-23 16:11:06 +08:00
openfeign 支持泛型反序列化的,为什么要去掉呢?
BBCCBB
2021-11-23 16:37:31 +08:00
feign 有 Decoder, 你可以实现自己的 Decoder 来处理. 不过你这个做法不太好..

直接 1 楼的方式, 写个 Util 方法来 unwrap 咯.
amoyiki
2021-11-23 17:31:43 +08:00
写个工具类即可
```java
public static <T> List<T> getFeignDataList(Callable<RspResult> feignFunc, Class<T> clazz) throws Exception {
RspResult ret = feignFunc.call();
if (ret.getCode() == 200) {
// 判断是否是有 items 数组,有的话取出 items 后在进行反序列化
List<T> ts = null;
String s = JsonUtils.objectToJson(ret.getData());
if (!StringUtils.isEmpty(s) && s.contains("items")) {
Map map = JsonUtils.objectToPojo(ret.getData(), Map.class);
ts = JsonUtils.objectToList(map.get("items"), clazz);

} else {
ts = JsonUtils.objectToList(ret.getData(), clazz);
}

return ts;
}
return null;
}
```
xuanbg
2021-11-23 18:40:24 +08:00
在网关上通过拦截器封装,所以内部调用获取到的 body 就是纯粹的数据。
zzl22100048
2021-11-23 20:47:32 +08:00
想统一封装从网关入手
bigbyto
2021-11-24 00:13:34 +08:00
贴一个我自己用的方案吧,这个的缺点是 Response 如果是非成功状态抛出异常是会被 feign 捕获包装重新抛出,里面包含了 decode 的信息。

public class AutoBoxingDecoder implements Decoder {
private final SpringDecoder delegate;

public AutoBoxingDecoder(SpringDecoder decoder) {
this.delegate = decoder;
}

@Override
public Object decode(Response response, Type type) throws IOException, FeignException {
if (type instanceof NormalResponse) {
return delegate.decode(response,type);
} else if (type instanceof ParameterizedType) {
ParameterizedType t = (ParameterizedType) type;
if (t.getRawType() instanceof NormalResponse) {
return delegate.decode(response,type);
}
}

ParameterizedType pt = new MyParameterizedType(type);
Object object = delegate.decode(response,pt);
if (object instanceof NormalResponse) {
return unpackOrThrow((NormalResponse<?>) object);
}

return object;
}

private Object unpackOrThrow(NormalResponse<?> res) {
if (res == null) {
throw new AppException("client response body is empty.");
}

if (!res.isSuccess()) {
throw new AppException(res.getMessage());
}

return res.getData();
}

static class MyParameterizedType implements ParameterizedType {

private final Type argument;

MyParameterizedType(Type argument) {
this.argument = argument;
}

@Override
public Type[] getActualTypeArguments() {
return new Type[]{argument};
}

@Override
public Type getRawType() {
return NormalResponse.class;
}

@Override
public Type getOwnerType() {
return null;
}
}
}
Geekerstar
2021-11-24 09:06:13 +08:00
@xuanbg feign 内部调用的,不走网关吧?
xuanbg
2021-11-24 10:31:07 +08:00
@Geekerstar 对呀,不走网关所以就没有封装呀。
9c04C5dO01Sw5DNL
2022-01-18 00:30:27 +08:00
xinQing
2022-01-28 16:12:44 +08:00
我也遇到过这样的,我是跟 8 楼一样的做法,搞个自定义 decoder 去拆包,如果发现错误就统一抛出,正常就拆包后,根据返回对象反序列化。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/817416

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX