前言
这一章我们来看TProtocol提供了哪些方法,重点介绍方法的功能,不对每个方法的源码实现做细致的分析,由于这一章牵扯到了上一层方法的调用问题,会有些难以理解,更多细节会在下一章详述。
数据结构
在Thrift中有一套规则,规定了如何将我们传入的对象转为自身可使用的参数,下面我们来看三个类。
TField代表一个字段,无论该字段是一个对象还是基本字段,都用TField表示,源码:
public class TField {
public final String name;//此字段的名称
public final byte type;//此字段的类型,取值见下面的TType源码
public final short id;//该字段在所在对象中的排序,这与Thrift源文件中的序号是对应的,也是Thrift用于将网络中获取的数据映射为本地Java对象
public TField() {
this("", TType.STOP, (short)0);
}
public TField(String n, byte t, short i) {
name = n;
type = t;
id = i;
}
//后面方法省略,没什么作用
}
//字段是何种类型
public final class TType {
public static final byte STOP = 0;//字段已经完结,可以结束了
public static final byte VOID = 1;//不用返回结果
public static final byte BOOL = 2;//boolean字段
public static final byte BYTE = 3;//byte字段
public static final byte DOUBLE = 4;//double字段
public static final byte I16 = 6;//16位编码字段
public static final byte I32 = 8;//32位编码字段
public static final byte I64 = 10;//64位编码字段
public static final byte STRING = 11;//string型字段
public static final byte STRUCT = 12;//对象型字段
public static final byte MAP = 13;//map结构字段
public static final byte SET = 14;//set结构字段
public static final byte LIST = 15;//list结构字段
public static final byte ENUM = 16;//enum结构字段
}
TStruct代表一个对象,当参数为一个对象时,用该结构来表示,源码:
public final class TStruct {
public final String name;//对象的 类名称,使客户端服务端知道如何将字节转为哪个类的对象
public TStruct() {
this("");
}
public TStruct(String n) {
name = n;
}
}
TMessage代表一条请求,在客户端数据前,必须先发送TMessage告诉服务端我们调用的是哪个方法,该条请求的类型,版本号。
public final class TMessage {
public final String name;//调用方法的名称
public final byte type;//该条message是代表什么类型的请求,详见TMessageType
public final int seqid;//Thrift版本号,用于校验
public TMessage() {
this("", TType.STOP, 0);
}
public TMessage(String n, byte t, int s) {
name = n;
type = t;
seqid = s;
}
@Override
public String toString() {
return "<TMessage name:'" + name + "' type: " + type + " seqid:" + seqid + ">";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + seqid;
result = prime * result + type;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TMessage other = (TMessage) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (seqid != other.seqid)
return false;
if (type != other.type)
return false;
return true;
}
}
public final class TMessageType {
public static final byte CALL = 1;//请求
public static final byte REPLY = 2;//响应
public static final byte EXCEPTION = 3;//异常
public static final byte ONEWAY = 4;//不大清楚含义,用处较少
}
TProtocol
我们还是先看下协议层的父类TProtocol源码:
public abstract class TProtocol {
protected TTransport trans_;//是不是很熟悉,就是用于读写
@SuppressWarnings("unused")
private TProtocol() {}
protected TProtocol(TTransport trans) {
trans_ = trans;
}
public TTransport getTransport() {
return trans_;
}
/**
* 所有的写方法
*/
//发送一条请求开始、结束时调用该方法
public abstract void writeMessageBegin(TMessage message) throws TException;
public abstract void writeMessageEnd() throws TException;
//写一个对象开始、结束调用的方法
public abstract void writeStructBegin(TStruct struct) throws TException;
public abstract void writeStructEnd() throws TException;
//写一个字段开始、结束调用的方法
public abstract void writeFieldBegin(TField field) throws TException;
public abstract void writeFieldEnd() throws TException;
//写字段结束标志调用的方法
public abstract void writeFieldStop() throws TException;
//map结构开始结束方法
public abstract void writeMapBegin(TMap map) throws TException;
public abstract void writeMapEnd() throws TException;
//list开始结束方法
public abstract void writeListBegin(TList list) throws TException;
public abstract void writeListEnd() throws TException;
//set开始结束方法
public abstract void writeSetBegin(TSet set) throws TException;
public abstract void writeSetEnd() throws TException;
//基本类型及string写方法,上面的所有方法最终都会调下面这些基本方法来实现
public abstract void writeBool(boolean b) throws TException;
public abstract void writeByte(byte b) throws TException;
public abstract void writeI16(short i16) throws TException;
public abstract void writeI32(int i32) throws TException;
public abstract void writeI64(long i64) throws TException;
public abstract void writeDouble(double dub) throws TException;
public abstract void writeString(String str) throws TException;
//将缓存写出去
public abstract void writeBinary(ByteBuffer buf) throws TException;
/**
* 所有的读的方法,全部都是与写相对应的,这里不做介绍
*/
public abstract TMessage readMessageBegin() throws TException;
public abstract void readMessageEnd() throws TException;
public abstract TStruct readStructBegin() throws TException;
public abstract void readStructEnd() throws TException;
public abstract TField readFieldBegin() throws TException;
public abstract void readFieldEnd() throws TException;
public abstract TMap readMapBegin() throws TException;
public abstract void readMapEnd() throws TException;
public abstract TList readListBegin() throws TException;
public abstract void readListEnd() throws TException;
public abstract TSet readSetBegin() throws TException;
public abstract void readSetEnd() throws TException;
public abstract boolean readBool() throws TException;
public abstract byte readByte() throws TException;
public abstract short readI16() throws TException;
public abstract int readI32() throws TException;
public abstract long readI64() throws TException;
public abstract double readDouble() throws TException;
public abstract String readString() throws TException;
public abstract ByteBuffer readBinary() throws TException;
public void reset() {}
//该类这里先忽略,是关于对象与字节之间转换的
public Class<? extends IScheme> getScheme() {
return StandardScheme.class;
}
}
关于二进制协议 ,在实现时也只是将boolean、long等转为字节数组发送出去,有兴趣的可以看看下面链接:
http://www.cnblogs.com/voipman/p/5125278.html
http://blog.youkuaiyun.com/zdq0394123/article/details/6597332
总结
本章看完大家可能还是一头雾水,虽然知道了方法的作用,但还是对于它的使用场景没有了解,主要因为牵扯到了Thrift如何发送数据的流程,这些问题在下一章都会一一详述。