前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >thrift/swift:服务端数据类型和client端数据类型之间的直接转换

thrift/swift:服务端数据类型和client端数据类型之间的直接转换

作者头像
10km
发布2019-05-25 21:49:18
1.1K0
发布2019-05-25 21:49:18
举报
文章被收录于专栏:10km的专栏

版权声明:本文为博主原创文章,转载请注明源地址。 https://cloud.tencent.com/developer/article/1433556

需求描述

我们知道,thrift/swift框架中,服务端的数据类型与client的类型是相互独立的,比如服务端有一个ClassA类型,到了client端,同样也会生成一个同名的类。服务端和client相互通信时,client的 ClassA会被转成数据流(二进制或HTML或JSON…),通过网络传输到服务端,服务端收到数据流后再转换服务端的ClassA,反之亦然。这个过程是由thrift框架自动完成的,对应用程序来说是透明的。

那么当我们希望client端应用程序与服务端共用同一个数据类型,也就是服务端的ClassA时,就需要一种从 client ClassA到服务端ClassA之间的直接转换,thrift/swift框架并没有提供这样的直接转换机制,该怎么办呢?

解决方案

首先需要找到thrift/swift将数据对象转换成数据流的地方。

研究了swift的代码,我在swift-codec-0.14.2.jar包中找到数据转换机制实现的地方,下面几个方法实现thrift数据对象转换数据流的基本功能:

代码语言:javascript
复制
/** 从一个数据对象Object,读取ThriftFieldMetadata指定的字段的值 */
com.facebook.swift.codec.internal.reflection.AbstractReflectionThriftCodec#getFieldValue(Object instance, ThriftFieldMetadata field)
/** 根据Map中字段值构造一个数据对象 */
com.facebook.swift.codec.internal.reflection.ReflectionThriftStructCodec#constructStruct(Map<Short, Object> data)
/** 从数据流protocol读取字段值转成数据对象 T */
T com.facebook.swift.codec.internal.reflection.ReflectionThriftStructCodec.read(TProtocol protocol)
/** 将数据对象instance写入数据流protocol */
void com.facebook.swift.codec.internal.reflection.ReflectionThriftStructCodec.write(T instance, TProtocol protocol)

通过这几个方法看懂了swift的数据对象转换机制,就可以参照这个机制实现服务端数据类型和client数据类型的直接转换。

具体代码参数gitee仓库中的代码:

https://gitee.com/l0km/common-java/blob/master/common-thrift/src/main/java/net/gdface/thrift/ThriftUtils.java

代码语言:javascript
复制
/** 构造{@code metadata}指定类型的实例并填充字段 */
public static <T>T constructStruct(Map<Short, Object> data,ThriftStructMetadata metadata) throws Exception;
/** 填充{@code instance}实例的字段 */
public static <T>T fillStructField(Map<Short, Object> data,ThriftStructMetadata metadata,T instance) 
        throws Exception
/** 获取{@code field}指定的字段值 */
public static Object getFieldValue(Object instance, ThriftFieldMetadata field) throws Exception ;
/** 根据{@code metadata}类型数据获取{@code instance}实例所有的字段值 */
public static Map<Short, Object> getFiledValues(Object instance, ThriftStructMetadata metadata);

应用示例

以下是调用上面的方法实现的转换器com.google.common.base.Function接口

代码语言:javascript
复制
import static com.google.common.base.Preconditions.*;
import java.util.Map;

import com.facebook.swift.codec.metadata.ThriftStructMetadata;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import static net.gdface.thrift.ThriftUtils.*;
/**
 * 有{@link com.facebook.swift.codec.ThriftStruct}注释的类型之间的转换
 * @author guyadong
 *
 * @param <L> 源数据类型,client或服务端java bean数据类型
 * @param <R> 目标数据类型,L对应的服务或client端java bean数据类型
 */
public class ThriftStructTransformer<L,R> implements Function<L,R>{
    /** 源数据类型的thrift数据结构描述对象 */
    private final ThriftStructMetadata leftMetadata;
    /** 目标数据类型的thrift数据结构描述对象 */
    private final ThriftStructMetadata rightMetadata;
    /** 构造方法 */
    public ThriftStructTransformer(Class<L> left, Class<R> right) {
        // 根据数据类型生成thrift数据结构描述对象
        this.leftMetadata= CATALOG.getThriftStructMetadata(checkNotNull(left,"left is null"));
        this.rightMetadata= CATALOG.getThriftStructMetadata(checkNotNull(right,"right is null"));
    }
    /** 源类型到目标数据类型转换实现 */
    @Override
    public R apply(L input) {
        if(null == input){
            return null;
        }
        try {
            // 读取所有字段值
            Map<Short, Object> data = getFiledValues(input,leftMetadata);
            // 根据字段值构造目标数据对象
            return constructStruct(data,rightMetadata);
        } catch (Exception e) {
            Throwables.throwIfUnchecked(e);
            throw new RuntimeException(e);
        }
    }
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder()
                .append("ThriftStructTransformer [leftClass=")
                .append(leftMetadata.getStructType())
                .append(", rightClass=")
                .append(rightMetadata.getStructType())
                .append("]");
        return builder.toString();
    }
}

完整代码参见:

https://gitee.com/l0km/common-java/blob/master/common-thrift/src/main/java/net/gdface/thrift/ThriftStructTransformer.java

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018年03月04日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 需求描述
  • 解决方案
  • 应用示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档