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();
}
}