Thrift 生成文件解析

thrift 文件

namespace java com.meituan.model

struct Pair {
        1: required string key;
        2: required string value;
        3: required i16 test1;
        4: optional i32 test2;
        5: optional i64 test3;
				6: optional i32 test4;
  			7: optional i32 test5;
   			// ... 65 个 i32 类型的元素
        67: optional i32 test65;
}

生成代码

// "Autogenerated by Thrift Compiler (0.9.3)"
public class Pair implements org.apache.thrift.TBase<Pair, Pair._Fields>, java.io.Serializable, Cloneable, Comparable<Pair> {
}

desc

private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Pair");
private static final org.apache.thrift.protocol.TField KEY_FIELD_DESC = new org.apache.thrift.protocol.TField("key", org.apache.thrift.protocol.TType.STRING, (short) 1);
private static final org.apache.thrift.protocol.TField VALUE_FIELD_DESC = new org.apache.thrift.protocol.TField("value", org.apache.thrift.protocol.TType.STRING, (short) 2);
private static final org.apache.thrift.protocol.TField TEST1_FIELD_DESC = new org.apache.thrift.protocol.TField("test1", org.apache.thrift.protocol.TType.I16, (short) 3);
private static final org.apache.thrift.protocol.TField TEST2_FIELD_DESC = new org.apache.thrift.protocol.TField("test2", org.apache.thrift.protocol.TType.I32, (short) 4);
private static final org.apache.thrift.protocol.TField TEST3_FIELD_DESC = new org.apache.thrift.protocol.TField("test3", org.apache.thrift.protocol.TType.I64, (short) 5);

STRUCT_DESC *_FIELD_DESC 是对 Thrift 定义字段的描述。

属性的描述由 writeStructBegin writeFieldBegin 方法写入 TProtocol。

属性

 public String key; // required
  public String value; // required
  public short test1; // optional
  public int test2; // optional
  public long test3; // optional
  public int test4; // optional

_Fields

_Fields 枚举类实现属性 ID 和属性名称的快速查找,没有属性的类型信息。

isset

private static final int __TEST1_ISSET_ID = 0;
  private static final int __TEST2_ISSET_ID = 1;
	// ...
  private static final int __TEST64_ISSET_ID = 63;
  private static final int __TEST65_ISSET_ID = 64;
  private BitSet __isset_bit_vector = new BitSet(65);

这个东东存在的意义是: JAVA基本数据类型 的属性是(说白了就是 0)是用户指定的还是默认值(脏数据)。

而 Java 中的引用数据类型存在 null。

上面 Thrift 文件生成 65 个 (i16,i32,i64) 类型的数据,是为了说明 isset 是如何实现的(BitSet)。即使用一个比特位(0,1)标识是否设置值。

假如只有 [1,8] 个 (i16,i32,i64) 类型的数据,还会使用 BitSet 实现嘛?

假如只有 (8,32] 个 (i16,i32,i64) 类型的数据,还会使用 BitSet 实现嘛?

假如只有 (32,64] 个 (i16,i32,i64) 类型的数据,还会使用 BitSet 实现嘛?

metaDataMap 元数据

public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
static {
    Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
    tmpMap.put(_Fields.KEY, new org.apache.thrift.meta_data.FieldMetaData("key", org.apache.thrift.TFieldRequirementType.REQUIRED, 
        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
    metaDataMap = Collections.unmodifiableMap(tmpMap);
    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(Pair.class, metaDataMap);
  	// ...
}

将每个生成类的字段信息保存在 FieldMetaData.structMap 中,没有发现有在任何地方使用到。

validate

public void validate() throws org.apache.thrift.TException {                                                                 
  // check for required fields                                                                                               
  if (key == null) {                                                                                                         
    throw new org.apache.thrift.protocol.TProtocolException("Required field 'key' was not present! Struct: " + toString());  
  }                                                                                                                          
  if (value == null) {                                                                                                       
    throw new org.apache.thrift.protocol.TProtocolException("Required field 'value' was not present! Struct: " + toString());
  }                                                                                                                          
  // alas, we cannot check 'test1' because it's a primitive and you chose the non-beans generator.                           
  // check for sub-struct validity                                                                                           
}                                                                                                                            

对 required 字段进行有效性检查,引用类型判断是否是 null,而对于Java 中的基本数据类型则无法进行检查。因为你找不到一个非正常数值区别与正常的数值。

schemes

public interface IScheme<T extends TBase> {
  // iproto to struct
  public void read(org.apache.thrift.protocol.TProtocol iproto, T struct) throws org.apache.thrift.TException;
  // struct to oproto
  public void write(org.apache.thrift.protocol.TProtocol oproto, T struct) throws org.apache.thrift.TException;
}

private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
static {
    schemes.put(StandardScheme.class, new PairStandardSchemeFactory());
    schemes.put(TupleScheme.class, new PairTupleSchemeFactory());
}
  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
    schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
  }

  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
    schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
  }

schemes 中保存了两个编解码的实现。默认使用 StandardScheme 的实现类。

 private static class PairStandardScheme extends StandardScheme<Pair> {
        public void read(org.apache.thrift.protocol.TProtocol iprot, Pair struct) throws org.apache.thrift.TException {
            org.apache.thrift.protocol.TField schemeField;
          	// 读取 STRUCT_DESC
            iprot.readStructBegin();
            while (true) {
              	// 读取 *_FIELD_DESC
                schemeField = iprot.readFieldBegin();
                if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
                    break;
                }
                switch (schemeField.id) {
                    case 1: // KEY
                        if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                            struct.key = iprot.readString();
                            struct.setKeyIsSet(true);
                        } else {
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                        }
                        break;
                    case 2: // VALUE
                        if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                            struct.value = iprot.readString();
                            struct.setValueIsSet(true);
                        } else {
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                        }
                        break;
                    case 3: // TEST1
                        if (schemeField.type == org.apache.thrift.protocol.TType.I16) {
                            struct.test1 = iprot.readI16();
                            struct.setTest1IsSet(true);
                        } else {
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                        }
                        break;
                    case 4: // TEST2
                        if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                            struct.test2 = iprot.readI32();
                            struct.setTest2IsSet(true);
                        } else {
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                        }
                        break;
                    case 5: // TEST3
                        if (schemeField.type == org.apache.thrift.protocol.TType.I64) {
                            struct.test3 = iprot.readI64();
                            struct.setTest3IsSet(true);
                        } else {
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                        }
                        break;
                    case 6: // TEST4
                        if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                            struct.test4 = iprot.readI32();
                            struct.setTest4IsSet(true);
                        } else {
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                        }
                        break;
                    case 7: // TEST5
                        if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                            struct.test5 = iprot.readI32();
                            struct.setTest5IsSet(true);
                        } else {
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                        }
                        break;
                    case 8: // TEST6
                        if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                            struct.test6 = iprot.readI32();
                            struct.setTest6IsSet(true);
                        } else {
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                        }
                        break;
                    case 9: // TEST7
                        if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                            struct.test7 = iprot.readI32();
                            struct.setTest7IsSet(true);
                        } else {
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                        }
                        break;
                    case 10: // TEST8
                        if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                            struct.test8 = iprot.readI32();
                            struct.setTest8IsSet(true);
                        } else {
                            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                        }
                        break;
                    default:
                        org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
                }
                iprot.readFieldEnd();
            }
            iprot.readStructEnd();

            // check for required fields of primitive type, which can't be checked in the validate method
            if (!struct.isSetTest1()) {
                throw new org.apache.thrift.protocol.TProtocolException("Required field 'test1' was not found in serialized data! Struct: " + toString());
            }
            struct.validate();
        }

        public void write(org.apache.thrift.protocol.TProtocol oprot, Pair struct) throws org.apache.thrift.TException {
            struct.validate();

            oprot.writeStructBegin(STRUCT_DESC);
            if (struct.key != null) {
                oprot.writeFieldBegin(KEY_FIELD_DESC);
                oprot.writeString(struct.key);
                oprot.writeFieldEnd();
            }
            if (struct.value != null) {
                oprot.writeFieldBegin(VALUE_FIELD_DESC);
                oprot.writeString(struct.value);
                oprot.writeFieldEnd();
            }
            oprot.writeFieldBegin(TEST1_FIELD_DESC);
            oprot.writeI16(struct.test1);
            oprot.writeFieldEnd();
            if (struct.isSetTest2()) {
                oprot.writeFieldBegin(TEST2_FIELD_DESC);
                oprot.writeI32(struct.test2);
                oprot.writeFieldEnd();
            }
            if (struct.isSetTest3()) {
                oprot.writeFieldBegin(TEST3_FIELD_DESC);
                oprot.writeI64(struct.test3);
                oprot.writeFieldEnd();
            }
            if (struct.isSetTest4()) {
                oprot.writeFieldBegin(TEST4_FIELD_DESC);
                oprot.writeI32(struct.test4);
                oprot.writeFieldEnd();
            }
            if (struct.isSetTest5()) {
                oprot.writeFieldBegin(TEST5_FIELD_DESC);
                oprot.writeI32(struct.test5);
                oprot.writeFieldEnd();
            }
            if (struct.isSetTest6()) {
                oprot.writeFieldBegin(TEST6_FIELD_DESC);
                oprot.writeI32(struct.test6);
                oprot.writeFieldEnd();
            }
            if (struct.isSetTest7()) {
                oprot.writeFieldBegin(TEST7_FIELD_DESC);
                oprot.writeI32(struct.test7);
                oprot.writeFieldEnd();
            }
            if (struct.isSetTest8()) {
                oprot.writeFieldBegin(TEST8_FIELD_DESC);
                oprot.writeI32(struct.test8);
                oprot.writeFieldEnd();
            }
            oprot.writeFieldStop();
            oprot.writeStructEnd();
        }
    }
发布了778 篇原创文章 · 获赞 323 · 访问量 209万+

猜你喜欢

转载自blog.csdn.net/lgh1992314/article/details/105286790
今日推荐