四 序列化机制
4.1 基本知识
- Thrift支持二进制,压缩格式,以及json格式数据的序列化和反序列化。开发人员可以更加灵活的选择协议的具体形式。协议是可自由扩展的,新版本的协议,完全兼容老的版本!
- 前面介绍到了protocol的一些基本知识,下面我们来详细看下他的用法
4.2 TProtocol
- 这是一个协议接口,我们可以看出他有多少个实现类
TBinaryProtocol
:是Thrift的默认协议,使用二进制编码格式进行数据传输,基本上直接发送原始数据TCompactProtocol
:压缩的、密集的数据传输协议,基于Variable-length quantity的zigzag 编码格式TJSONProtocol
:以JSON (JavaScript Object Notation)数据编码协议进行数据传输TDebugProtocol
:常常用以编码人员测试,以文本的形式展现方便阅读
基本方法
/**
* Writing methods. 写方法
*/
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;
public abstract void writeMapBegin(TMap map) throws TException;
public abstract void writeMapEnd() throws TException;
public abstract void writeListBegin(TList list) throws TException;
public abstract void writeListEnd() throws TException;
public abstract void writeSetBegin(TSet set) throws TException;
public abstract void writeSetEnd() throws TException;
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;
/**
* Reading methods. 读方法
*/
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;
4.3 TCompactProtocol
- TCompactProtocol2 是 THRIFT-110 中指定的紧凑协议的 Java 实现。减少结构开销的基本方法是 a) 在所有地方使用可变长度整数 b) 尽可能使用未使用的位。
- 您的节省显然会根据结构的具体构成而有所不同,但总的来说,您拥有的字段、嵌套结构、短字符串和集合以及低值 i32 和 i64 字段越多,您将看到的好处就越多。
- 所有类型:
/**
* All of the on-wire type codes.
*/
private static class Types {
public static final byte BOOLEAN_TRUE = 0x01;
public static final byte BOOLEAN_FALSE = 0x02;
public static final byte BYTE = 0x03;
public static final byte I16 = 0x04;
public static final byte I32 = 0x05;
public static final byte I64 = 0x06;
public static final byte DOUBLE = 0x07;
public static final byte BINARY = 0x08;
public static final byte LIST = 0x09;
public static final byte SET = 0x0A;
public static final byte MAP = 0x0B;
public static final byte STRUCT = 0x0C;
}
源码分析
package com.example.thrift.client;
import com.example.thrift.thrift.person;
import com.example.thrift.thrift.personservice;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.layered.TFramedTransport;
/**
* @Author shu
* @Description 客服端
**/
public class ThriftClient {
public static void main(String[] args) {
TTransport transport =null;
try {
// 连接
transport = new TFramedTransport(new TSocket("127.0.0.1",8803),600);
// 协议
TProtocol protocol = new TCompactProtocol(transport);
// 调用方法
personservice.Client client = new personservice.Client(protocol);
// 打开连接
transport.open();
// 调用方法
person result = client.getPersonInfoByUserNmae("哈哈哈哈");
System.out.println("Result =: " + result);
} catch (TException e) {
e.printStackTrace();
} finally {
if (null != transport) {
transport.close();
}
}
}
}
- 点入我们自定的方法getPersonInfoByUserNmae,可以看到thrift生成的服务
public person getPersonInfoByUserNmae(String username) throws personexception, org.apache.thrift.TException
{
send_getPersonInfoByUserNmae(username);
return recv_getPersonInfoByUserNmae();
}
public void send_getPersonInfoByUserNmae(String username) throws org.apache.thrift.TException
{
getPersonInfoByUserNmae_args args = new getPersonInfoByUserNmae_args();
args.setUsername(username);
// 关键方法,发送数据
sendBase("getPersonInfoByUserNmae", args);
}
- 进入sendBase方法,可以看到他实际调用了TCompactProtocol的实现方法
protected void sendBase(String methodName, TBase<?,?> args) throws TException {
sendBase(methodName, args, TMessageType.CALL);
}
// 将数据写入具体的实现协议中
private void sendBase(String methodName, TBase<?,?> args, byte type) throws TException {
// 写入开始,协议基本信息
oprot_.writeMessageBegin(new TMessage(methodName, type, ++seqid_));
// 写入
args.write(oprot_);
// 写入结束
oprot_.writeMessageEnd();
// 刷新数据
oprot_.getTransport().flush();
}
/**将消息头写入线路。紧凑协议消息包含协议版本
* Write a message header to the wire. Compact Protocol messages contain the
* protocol version so we can migrate forwards in the future if need be.
*/
@Override
public void writeMessageBegin(TMessage message) throws TException {
// 协议编号
writeByteDirect(PROTOCOL_ID);
// 版本
writeByteDirect((VERSION & VERSION_MASK) | ((message.type << TYPE_SHIFT_AMOUNT) & TYPE_MASK));
// 序列号
writeVarint32(message.seqid);
// 消息名
writeString(message.name);
}
- 生成的 Thrift 对象的通用基本接口:TSerializable
public interface TSerializable {
/**
* Reads the TObject from the given input protocol.
*从协议读取对象
* @param iprot Input protocol
*/
public void read(TProtocol iprot) throws TException;
/**
* Writes the objects out to the protocol
*将对象写入协议
* @param oprot Output protocol
*/
public void write(TProtocol oprot) throws TException;
}
- 显然这调用的是thrift生成的方法
public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
scheme(oprot).write(oprot, this);
}
- 调用TCompactProtocol方法开始写入
public void write(org.apache.thrift.protocol.TProtocol oprot, getPersonInfoByUserNmae_args struct) throws org.apache.thrift.TException {
struct.validate();
oprot.writeStructBegin(STRUCT_DESC);
if (struct.username != null) {
oprot.writeFieldBegin(USERNAME_FIELD_DESC);
oprot.writeString(struct.username);
oprot.writeFieldEnd();
}
oprot.writeFieldStop();
oprot.writeStructEnd();
}
}
- 与写入方法不同的是,读方法调用的是TSerializabl接口的read实现类,其实也是调用了thrift生成的service中的方法。
public interface IScheme<T extends TBase> {
public void read(org.apache.thrift.protocol.TProtocol iproto, T struct) throws org.apache.thrift.TException;
public void write(org.apache.thrift.protocol.TProtocol oproto, T struct) throws org.apache.thrift.TException;
}