// Thrift 消息類型
public final class TMessageType {
public static final byte CALL = 1; // 調用遠程方法,並且期待對方發送響應
public static final byte ONEWAY = 4; // 調用遠程方法,不期待響應。即沒有步驟3,4
public static final byte REPLY = 2; // 表明處理完成,響應正常返回
public static final byte EXCEPTION = 3; // 表明出理出錯
}
// Thrift 支持的數據類型
public final class TType {
// 標識屬性的結尾(即讀到 STOP 表明後邊沒有屬性了)
public static final byte STOP = 0;
public static final byte VOID = 1;
public static final byte BOOL = 2; // 對應於 java 中的 boolean
public static final byte BYTE = 3; // byte
public static final byte DOUBLE = 4; // double
public static final byte I16 = 6; // short
public static final byte I32 = 8; // int
public static final byte I64 = 10; // long
public static final byte STRING = 11; // String
// 類似於 C 語言中的結構體
public static final byte STRUCT = 12;
public static final byte MAP = 13;
public static final byte SET = 14;
public static final byte LIST = 15;
public static final byte ENUM = 16;
}
// thrift 消息頭(方法名稱:方法類型:方法序號)
public final class TMessage {
public final String name;
public final byte type;
public final int seqid;
// ...
}
// 字段消息頭:字段名稱-字段類型-字段序號
public class TField {
public final String name;
public final byte type;
public final short id;
}
// List 消息頭 元素類型-元素個數
public final class TList {
public final byte elemType;
public final int size;
}
// Map 消息頭 鍵類型-值類型-元素個數
public final class TMap {
public final byte keyType;
public final byte valueType;
public final int size;
}
// Set 消息頭 元素類型-元素個數
public final class TSet {
public final byte elemType;
public final int size;
}
// Struct 消息頭: XXX_args XXX_result 的消息頭說明
public final class TStruct {
public final String name;
}
TMessage 的 equals 方法比較了 name,而 TField 中沒有,想想爲什麼?
因爲在 thrift 中,使用參數類型和索引,區分是哪一個參數。而 TMessage 描述的方法調用的元數據。
string sayBye(1: optional string name, 2: optional i32 age)
TField 的 id 屬性,表示是參數相對位置的索引,如下方的 1,2。
struct Request {
1: required i32 age;
2: required string name;
}
id 爲何是 short 類型?引申爲 Java 中參數列表支持多少個參數。
https://zhuanlan.zhihu.com/p/44086976
java 中參數列表最大支持 255 個單位長度。
public abstract class TProtocolDecorator extends TProtocol {
private final TProtocol concreteProtocol;
public TProtocolDecorator(TProtocol protocol) {
super(protocol.getTransport());
concreteProtocol = protocol;
}
// ...
}
TProtocolDecorator採用裝飾者模式,將調用委託給內部的 concreteProtocol。
public class TMultiplexedProtocol extends TProtocolDecorator {
public static final String SEPARATOR = ":";
private final String SERVICE_NAME;
public TMultiplexedProtocol(TProtocol protocol, String serviceName) {
super(protocol);
SERVICE_NAME = serviceName;
}
@Override
public void writeMessageBegin(TMessage tMessage) throws TException {
if (tMessage.type == TMessageType.CALL || tMessage.type == TMessageType.ONEWAY) {
super.writeMessageBegin(new TMessage(
SERVICE_NAME + SEPARATOR + tMessage.name,
tMessage.type,
tMessage.seqid
));
} else {
super.writeMessageBegin(tMessage);
}
}
}
使用
TSocket transport = new TSocket("localhost", 9090);
transport.open();
TBinaryProtocol protocol = new TBinaryProtocol(transport);
TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator");
Calculator.Client service = new Calculator.Client(mp);
TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport");
WeatherReport.Client service2 = new WeatherReport.Client(mp2);
System.out.println(service.add(2,2));
System.out.println(service2.getTemperature());