thrift/swift:ThriftMethodProcessor代码分析

thrift是一种跨语言的RPC框架,为了保证在各种语言下都能正确表述,IDL语言在设计的时候就只能选取各种语言的共性。 比如对于null,虽然在java中定义一个字段为Integer类型,那么这个字段就可以为null,但thrift不允许primitive类型的数据字段为null,因为在c/c++的struct的字段中没有null的概念。做为方法的参数传递,primitive类型也是同样的道理。 所以thrift client 发送调用服务方法时,如果方法的参数类型为Integer,你即使将该参数设置为null,服务端收到的值也不是null,而是0.

经过反复跟踪我总算找到将null参数转为0的位置,就在服务端com.facebook.swift.service.ThriftMethodProcessor的私有方法readArguments中,下面是readArguments的代码,注意代码中作者添加的中文注释

private Object[] readArguments(TProtocol in)
            throws Exception
    {
        try {
            int numArgs = method.getParameterTypes().length;
            // 初始化参数数组,初始值都为null
            Object[] args = new Object[numArgs];
            TProtocolReader reader = new TProtocolReader(in);

            // 先从收到的数据库根据fieldId 将不为null的服务方法参数解析出来,
            // 为null的参数不在收到的数据中出现
            // 所以这个循环结束时,不为null的参数已经被正确解析并保存到args的对应位置了
            // client填null(原本就是null)的参数对应的位置就是null,
            reader.readStructBegin();
            while (reader.nextField()) {
                short fieldId = reader.getFieldId();

                ThriftCodec<?> codec = parameterCodecs.get(fieldId);
                if (codec == null) {
                    // unknown field
                    reader.skipFieldData();
                }
                else {
                    // 将参数调用对应用的解码器ThriftCodec解析成正确的数据类型,
                    // 存入arg数组对应的位置
                    args[thriftParameterIdToJavaArgumentListPositionMap.get(fieldId)] = reader.readField(codec);
                }
            }
            reader.readStructEnd();

            // 在下面这个循环中,对args数组中为null的参数进行检查,
            // 如果是primitive类型则调用 Defaults.defaultValue方法返回缺省值
            // 比如对于Integer类型缺省值就是0
            // 如果删除掉这一整段循环代码,service端收到的Integer参数就可以是null
            int argumentPosition = 0;
            for (ThriftFieldMetadata argument : parameters) {
                if (args[argumentPosition] == null) {
                    Type argumentType = argument.getThriftType().getJavaType();

                    if (argumentType instanceof Class) {
                        Class<?> argumentClass = (Class<?>) argumentType;
                        argumentClass = Primitives.unwrap(argumentClass);
                        args[argumentPosition] = Defaults.defaultValue(argumentClass);
                    }
                }
                argumentPosition++;
            }

            return args;
        }
        catch (TProtocolException e) {
            // TProtocolException is the only recoverable exception
            // Other exceptions may have left the input stream in corrupted state so we must
            // tear down the socket.
            throw new TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage());
        }
    }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏calvin

【nodejs】让nodejs像后端mvc框架(asp.net mvc)一样处理请求--参数自动映射篇(6/8)

路由、action的扫描、发现、注册搞定之后,后来我发现在我们的action里面获取参数往往都是通过request对象来一个一个获取。同样的一行代码我们不厌其烦...

12420
来自专栏me的随笔

Python知识梳理

我们可以使用type()函数类获取对象的类型,Python3中内置数据类型包括:None,int,float,complex,str,list,dict,tup...

15720
来自专栏我是攻城师

Apache Pig学习笔记之内置函数(三)

45040
来自专栏章鱼的慢慢技术路

牛客网_Go语言相关练习_判断&选择题(4)

错误指的是可能出现问题的地方出现了问题,比如打开一个文件时失败,这种情况在人们的意料之中;而异常指的是不应该出现问题的地方出现了问题,比如引用了空指针,这种情况...

12520
来自专栏飞雪无情的博客

从Java到Golang快速入门

Golang从09年发布,中间经历了多个版本的演进,已经渐渐趋于成熟,并且出现了很多优秀的开源项目,比如我们熟知的docker,etcd,kubernetes等...

12330
来自专栏Python爱好者

Python高效编程(五)

11330
来自专栏Ryan Miao

java基础面试题

参考:http://blog.csdn.net/jackfrued/article/details/44921941 说未经允许不转载,我只好参考了。 1.面向...

37450
来自专栏AhDung

【手记】注意BinaryWriter写string的小坑——会在string前加上长度前缀length-prefixed

之前以为BinaryWriter写string会严格按构造时指定的编码(不指定则是无BOM的UTF8)写入string的二进制,如下面的代码:

30730
来自专栏决胜机器学习

PHP数据结构(三)——运用栈实现括号匹配

PHP数据结构(三)——运用栈实现括号匹配 (原创内容,转载请注明来源,谢谢) 栈在数据结构上是一种特殊的线性表,其限制是仅允许在表的一端进行插入和删除运算,...

43860
来自专栏跟着阿笨一起玩NET

C# TextBox 扩展方法数据验证

      查看公司项目代码时,存在这样一个问题:winform界面上有很多信息填写,提交后台服务器更新,但数据的合法验证及值的转换却不太敢恭维,一堆的if判断...

12310

扫码关注云+社区

领取腾讯云代金券