V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Geekerstar
V2EX  ›  Java

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

  •  
  •   Geekerstar · 2021-11-23 15:37:31 +08:00 · 2959 次点击
    这是一个创建于 1121 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    第 1 条附言  ·  2021-11-23 17:18:09 +08:00
    之前的做法是用 @RestControllerAdvice 来统一封装响应参数,并且提供不封装统一响应的注解,好处是每个接口不需要写 Response<String> 而是直接返回 String 就行了,起初发现这种方案对 Knife4j 有影响,但是可以通过一些配置来解决。然后就是 feign 调用的时候,不好判断是否需要加上统一响应。


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

    直接 1 楼的方式, 写个 Util 方法来 unwrap 咯.
    amoyiki
        5
    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
        6
    xuanbg  
       2021-11-23 18:40:24 +08:00
    在网关上通过拦截器封装,所以内部调用获取到的 body 就是纯粹的数据。
    zzl22100048
        7
    zzl22100048  
       2021-11-23 20:47:32 +08:00 via iPhone
    想统一封装从网关入手
    bigbyto
        8
    bigbyto  
       2021-11-24 00:13:34 +08:00   ❤️ 1
    贴一个我自己用的方案吧,这个的缺点是 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
        9
    Geekerstar  
    OP
       2021-11-24 09:06:13 +08:00
    @xuanbg feign 内部调用的,不走网关吧?
    xuanbg
        10
    xuanbg  
       2021-11-24 10:31:07 +08:00
    @Geekerstar 对呀,不走网关所以就没有封装呀。
    9c04C5dO01Sw5DNL
        11
    9c04C5dO01Sw5DNL  
       2022-01-18 00:30:27 +08:00
    xinQing
        12
    xinQing  
       2022-01-28 16:12:44 +08:00
    我也遇到过这样的,我是跟 8 楼一样的做法,搞个自定义 decoder 去拆包,如果发现错误就统一抛出,正常就拆包后,根据返回对象反序列化。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3230 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 12:41 · PVG 20:41 · LAX 04:41 · JFK 07:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.