定义一个thrift接口:
service ThriftService {
void myFunc();
}
通过 thrift compiler 生成 java 代码
thrift --gen java ThriftService.thrift
生成了Thrift的接口类:
public class ThriftService {
// 同步和异步调用接口
public interface Iface {...}
public interface AsyncIface {...}
// 接口的实现类(同步和异步)
public static class Client {...}
public static class AsyncClient {...}
}
实现server端:
public class Server {
public static class ThriftServiceImpl implements ThriftService.Iface{
@Override
public String myFunc(String name) throws TException {
return "My Thrift Function";
}
}
public static void main(String[] args) throws TTransportException {
// 获取实现
ThriftServiceImpl impl= new ThriftServiceImpl();
// 接口与实现类的绑定关系在这里完成
HelloWorldService.Processor<ThriftServiceImpl> processor = new ThriftService.Processor<ThriftServiceImpl>(impl);
// 构建服务器
TServerTransport serverTransport = new TServerSocket(9090);
TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));
server.serve();
}
}
client端可以直接调用接口,二不用关心具体的实现类。
public class Client {
public static void main(String[] args) throws TException {
TTransport transport = new TSocket("localhost", 9090);
transport.open();
TProtocol protocol = new TBinaryProtocol(transport);
ThriftService.Client client = new ThriftService.Client(protocol);
client.myFunc();
transport.close();
}
}
或者:
TFastFramedTransport transport = new TFastFramedTransport(new TSocket(host, port));
TBinaryProtocol protocol = new TBinaryProtocol(transport);
SimpleSerice.Client client = new SimpleService.Client(protocol);
try {
transport.open();
client.myFunc();
} finally {
transport.close();
}
通信层协议,使用TTransport接口来描述,Thrift 提供了几种 transport 类供使用:
需要注意的是,transport 客户端要和服务端对应,比如如果要对 NIO 模型的服务端进行调研,transport 就必须使用 TFramedTransport或TFastFramedTransport。
传输层协议,引用 transport 并提供 thrift 的序列化协议,Thrift 也提供了几种常用的传输协议:
首先创建代理类,这里只需要引用 thrift 接口中的 Service 类,并通过引用发现内部 Client 类:
public class ThriftClientProxy implements InvocationHandler {
private Class clazz;
private Class clientClazz;
private String host;
private int port;
public Object newInstance(Class clazz, String host, int port) {
this.clazz = clazz;
this.host = host;
this.port = port;
this.clientClazz = Class.forName(classs.getName() + "$Client");
return Proxy.newProxyInstance(
getClass().getClassLoader(),
clientClazz.getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
TFastFramedTransport transport = new TFastFramedTransport(new TSocket(host, port));
TBinaryProtocol protocol = new TBinaryProtocol(transport);
Class[] classes = {TProtocol.class};
try {
transport.open();
return method.invoke(clientClazz.getConstructor(classes).newInstance(protocol), args);
}
finally {
transport.close();
}
}
}
之后将相应的 Iface 注册到 IOC 容器中即可。
@Configuration
public class ThriftClientConfiguration {
@Value("${simple.service.host}")
private String host;
@Value("${simple.service.port}")
private int port;
@Bean
public SimpleService.Iface thriftClient() {
return (SimpleService.Iface) new ThriftClientProxy().newInstance(SimpleService.class, host, port);
}
}
业务代码中只需要注入 SimpleService.Iface,并直接调用接口方法,而完全不需要关注内部逻辑实现。