Thrift 定義文件
model.thrift
namespace java com.meituan.model
struct Request {
1: required i32 age;
2: required string name;
}
struct Response {
1: required i16 code;
2: required string msg;
}
helloservice.thrift
namespace java com.meituan.service
include "model.thrift"
service HelloService {
model.Response sayHello(1: model.Request req)
}
服務端實現
public class HelloServiceImpl implements HelloService.Iface {
@Override
public Response sayHello(Request req) throws TException {
System.out.println(req);
Response response = new Response();
response.setMsg("hi");
response.setCode((short) 255);
return response;
}
}
服務端
public class Server {
public static void main(String[] args) {
TProcessor tprocessor = new HelloService.Processor<HelloService.Iface>(new HelloServiceImpl());
TServerSocket serverTransport = null;
try {
serverTransport = new TServerSocket(6666);
} catch (TTransportException e) {
e.printStackTrace();
}
TServer.Args tArgs = new TServer.Args(serverTransport);
tArgs.processor(tprocessor);
tArgs.protocolFactory(new TBinaryProtocol.Factory());
TServer server = new TSimpleServer(tArgs);
server.serve();
}
}
客戶端
public class Client {
public static void main(String[] args) {
TTransport transport = new TSocket("127.0.0.1", 6666, 1000);
try {
transport.open();
} catch (TTransportException e) {
e.printStackTrace();
}
TProtocol protocol = new TBinaryProtocol(transport);
HelloService.Client client = new HelloService.Client(protocol);
Request request = new Request();
request.setAge(27);
request.setName("lgh");
try {
Response response = client.sayHello(request);
System.out.println(response);
} catch (TException e) {
e.printStackTrace();
}
transport.close();
}
}
編碼(序列化):將對象轉換爲字節流
解碼(反序列化):編碼的逆過程
編碼過程
client.sayHello(request) --> com.meituan.service.HelloService.Client#sayHello
Client 由 Thrift 爲我們生成。
public com.meituan.model.Response sayHello(com.meituan.model.Request req) throws org.apache.thrift.TException
{
send_sayHello(req);
return recv_sayHello();
}
send_sayHello(req) --> com.meituan.service.HelloService.Client#send_sayHello
public void send_sayHello(com.meituan.model.Request req) throws org.apache.thrift.TException
{
sayHello_args args = new sayHello_args();
args.setReq(req);
sendBase("sayHello", args);
}
方法名_args 是對請求參數的封裝
sendBase(“sayHello”, args) --> org.apache.thrift.TServiceClient#sendBase(java.lang.String, org.apache.thrift.TBase<?,?>)
TServiceClient: A TServiceClient is used to communicate with a TService implementation across protocols and transports.
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 {
// 編碼 1:寫入 Thrift 請求消息頭
oprot_.writeMessageBegin(new TMessage(methodName, type, ++seqid_));
args.write(oprot_);
oprot_.writeMessageEnd();
oprot_.getTransport().flush();
}
args.write(oprot_) --> com.meituan.service.HelloService.sayHello_args#write
public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
}
schemes 對應的類型
private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
static {
schemes.put(StandardScheme.class, new sayHello_argsStandardSchemeFactory());
schemes.put(TupleScheme.class, new sayHello_argsTupleSchemeFactory());
}
TProtocol.getScheme()
默認返回
public Class<? extends IScheme> getScheme() {
return StandardScheme.class;
}
所以 schemes.get(oprot.getScheme()).getScheme()
返回的 sayHello_argsStandardSchemeFactory
getScheme
方法返回的 sayHello_argsStandardScheme
private static class sayHello_argsStandardSchemeFactory implements SchemeFactory {
public sayHello_argsStandardScheme getScheme() {
return new sayHello_argsStandardScheme();
}
}
args.write(oprot_)
調用的是 com.meituan.service.HelloService.sayHello_args.sayHello_argsStandardScheme#write
public void write(org.apache.thrift.protocol.TProtocol oprot, sayHello_args struct) throws org.apache.thrift.TException {
// 對請求參數(required 標識的引用類型的參數)進行非空檢查
struct.validate();
// 編碼 2:空
oprot.writeStructBegin(STRUCT_DESC);
if (struct.req != null) {
// 編碼 3:寫入 1 字節的參數類型,2 字節的參數序列號
oprot.writeFieldBegin(REQ_FIELD_DESC);
//
struct.req.write(oprot);
// 編碼13:什麼也不做
oprot.writeFieldEnd();
}
// 編碼 14:寫入 1 字節的(00000000)
oprot.writeFieldStop();
// 編碼 15:空
oprot.writeStructEnd();
}
struct.req.write(oprot) --> com.meituan.model.Request.RequestStandardScheme#write
public void write(org.apache.thrift.protocol.TProtocol oprot, Request struct) throws org.apache.thrift.TException {
struct.validate();
// 編碼 4:空
oprot.writeStructBegin(STRUCT_DESC);
// 編碼 5:寫入 1 字節的參數類型,2 字節的參數序列號
oprot.writeFieldBegin(AGE_FIELD_DESC);
// 編碼 6:寫入 age
oprot.writeI32(struct.age);
// 編碼 7:空
oprot.writeFieldEnd();
if (struct.name != null) {
// 編碼 8:寫入 1 字節的參數類型,2 字節的參數序列號
oprot.writeFieldBegin(NAME_FIELD_DESC);
// 編碼 9:寫入 name
oprot.writeString(struct.name);
// 編碼 10:空
oprot.writeFieldEnd();
}
// 編碼 11:寫入 1 字節的(00000000)
oprot.writeFieldStop();
// 編碼 12:空
oprot.writeStructEnd();
}