http://anruence.com/2018/06/27/enum-thrift/
问题
在用注解定义的Thrift enum 中,如果客户端端和服务端的enum定义不同,比如调换了enum中的枚举值的顺序,就会发生调用端发送的枚举参数与服务端解析得到的枚举参数不一致的问题。
猜想
java 中的enum类的每一个具体的枚举值都有一个ordinal,代表其声明顺序,从零开始。thrift在序列化和反序列化时会将枚举值转换为一个整数传递,所以枚举值的具体含义与调用端和服务端各自的enum代码中声明顺序有关。
Thrift 注解的实现中对于thrift中每个关键字都有对应的编解码器,enum对应的为EnumThriftCodec<T extends Enum,这个类继承了接口ThriftCodec 。具体代码如下:
1
|
package com.facebook.swift.codec.internal;
|
初步结论
现在总结一下,Thrift 注解方式会将枚举值编码成一个int进行网络传输,而在处理具体的枚举值与整数之间的对应关系的时候有两种策略:
如果枚举类显式声明了枚举值与整数之间的对应关系,则根据声明的规则进行编解码
如果枚举类中没有显式声明对应关系,则根据声明顺序的索引进行编解码。
具备了以上知识,就能解答文章最开始的问题了:如果客户端和服务端的枚举类里没有显式声明枚举值和整数值的对应关系,那么在编解码的时候的对应关系就是枚举值的声明顺序,如果两端的枚举类中枚举值的顺序不一致,就会导致两端编解码的的枚举值不一致。
深入探究
接下来再进一步探索,EnumThriftCodec如何判断一个枚举类是否声明了枚举值到整数的对应关系?为了回答这个问题,需要首先弄清楚EnumThriftCodec中的成员变量EnumMetadata的具体内容:
ThriftEnumMetadata.java
1
|
/* |