下面將通過一個(gè)實(shí)例來講解Thrift的使用方法:
1. 定義 idl文件,用來描述將要生成的數(shù)據(jù)通訊內(nèi)容API接口,以下面一個(gè)簡單例子來說明service.idl
namespace java com.xmatthew.thrift.demo
struct Info {
1: string key,
2: binary value,
}
service DemoService{
void add(1:string key, 2:binary value);
binary get(1:string key),
}
說明:struct Info {
1: string key,
2: binary value,
}
service DemoService{
void add(1:string key, 2:binary value);
binary get(1:string key),
}
namespace 表示目錄結(jié)構(gòu),生成java時(shí)會(huì)產(chǎn)生java的package
struct 表示數(shù)據(jù)結(jié)構(gòu)體,在java下是一個(gè)bean對(duì)象,在c則對(duì)應(yīng)struct結(jié)構(gòu)
service 表示服務(wù)類, 在java會(huì)生成DemoService.java。 提供兩個(gè)接口方法,客戶端和服務(wù)端都會(huì)擁有
2. 生成特定語言源文件,下面以java為例
thrift-0.6.0.exe -r --gen java service.idl
運(yùn)行成功后,會(huì)生成gen-java文件,下面就是源碼文件
本例中會(huì)產(chǎn)生兩個(gè)文件
Info.java
DemoService.java
3. 開發(fā)客戶端
有了這兩個(gè)文件后,接下來就需要把thrift的java類庫引進(jìn)來,就可以開發(fā)客戶端部分了
首先新建一個(gè)LocalClient類,繼承于DemoServer.Client類,源碼如下:
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import com.xmatthew.thrift.demo.DemoService.Client;
/**
* @author xiemalin
*
*/
public class LocalClient extends Client {
private TTransport transport;
public LocalClient(TProtocol prot,int port, TTransport ftransport) throws TTransportException {
super(prot);
this.transport = ftransport;
}
public void close(){
this.transport.close();
}
}
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import com.xmatthew.thrift.demo.DemoService.Client;
/**
* @author xiemalin
*
*/
public class LocalClient extends Client {
private TTransport transport;
public LocalClient(TProtocol prot,int port, TTransport ftransport) throws TTransportException {
super(prot);
this.transport = ftransport;
}
public void close(){
this.transport.close();
}
}
接下來為了方便使用,創(chuàng)建一個(gè)工廠類, 包括main方法,進(jìn)行使用示例
import java.io.IOException;
import java.nio.ByteBuffer;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransportException;
public class ClientFactory {
public static LocalClient getClient(String ip,int port) throws TTransportException, IOException{
TSocket transport = new TSocket(ip,port);
TProtocol protocol = new TBinaryProtocol(transport);
transport.open();
LocalClient client = new LocalClient(protocol, port,transport) ;
return client;
}
public static void main(String[] args) throws IOException, TException {
LocalClient client = ClientFactory.getClient("localhost", 8900);
ByteBuffer bb = ByteBuffer.wrap("Hello".getBytes());
client.add("abc", bb);
System.out.println("ok");
System.out.println(new String(client.get("aaa").array()));
}
}
import java.nio.ByteBuffer;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransportException;
public class ClientFactory {
public static LocalClient getClient(String ip,int port) throws TTransportException, IOException{
TSocket transport = new TSocket(ip,port);
TProtocol protocol = new TBinaryProtocol(transport);
transport.open();
LocalClient client = new LocalClient(protocol, port,transport) ;
return client;
}
public static void main(String[] args) throws IOException, TException {
LocalClient client = ClientFactory.getClient("localhost", 8900);
ByteBuffer bb = ByteBuffer.wrap("Hello".getBytes());
client.add("abc", bb);
System.out.println("ok");
System.out.println(new String(client.get("aaa").array()));
}
}
這樣客戶端部分已經(jīng)開發(fā)完成,非常快。
4. 開發(fā)服務(wù)器端部分, 新建一個(gè)Server 類, 該類實(shí)現(xiàn)于 DemoService.Iface接口(實(shí)現(xiàn)要求的兩個(gè)方法即可)
這里代碼中,可需要使用thrift的類庫,開啟Socket服務(wù)即可。
完整源代碼如下:
import java.nio.ByteBuffer;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TBinaryProtocol.Factory;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.server.TThreadPoolServer.Args;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
import org.apache.thrift.transport.TTransportException;
import com.xmatthew.thrift.demo.DemoService;
import com.xmatthew.thrift.demo.DemoService.Iface;
public class Server implements Iface {
private final int port ;
private final TThreadPoolServer tr_server;
public Server(int _port) throws TTransportException{
this.port = _port;
Factory protoFactory = new TBinaryProtocol.Factory(true, true);
TServerTransport serverTransport = new TServerSocket(port);
DemoService.Processor processor = new DemoService.Processor(this);
tr_server = new TThreadPoolServer(new Args(serverTransport).processor(processor)
.protocolFactory(protoFactory));
}
public void run(){
tr_server.serve();
}
public synchronized void close(){
tr_server.stop();
}
public void add(String key, ByteBuffer value) throws TException {
System.out.println("invoke 'add'("+key+","+new String(value.array())+")");
}
public ByteBuffer get(String key) throws TException {
System.out.println("invoke 'set'("+key+")");
ByteBuffer bb = ByteBuffer.wrap("get success".getBytes());
return bb;
}
public static void main(String[] args) throws TTransportException {
Server server = new Server(8900);
server.run();
}
}
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TBinaryProtocol.Factory;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.server.TThreadPoolServer.Args;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
import org.apache.thrift.transport.TTransportException;
import com.xmatthew.thrift.demo.DemoService;
import com.xmatthew.thrift.demo.DemoService.Iface;
public class Server implements Iface {
private final int port ;
private final TThreadPoolServer tr_server;
public Server(int _port) throws TTransportException{
this.port = _port;
Factory protoFactory = new TBinaryProtocol.Factory(true, true);
TServerTransport serverTransport = new TServerSocket(port);
DemoService.Processor processor = new DemoService.Processor(this);
tr_server = new TThreadPoolServer(new Args(serverTransport).processor(processor)
.protocolFactory(protoFactory));
}
public void run(){
tr_server.serve();
}
public synchronized void close(){
tr_server.stop();
}
public void add(String key, ByteBuffer value) throws TException {
System.out.println("invoke 'add'("+key+","+new String(value.array())+")");
}
public ByteBuffer get(String key) throws TException {
System.out.println("invoke 'set'("+key+")");
ByteBuffer bb = ByteBuffer.wrap("get success".getBytes());
return bb;
}
public static void main(String[] args) throws TTransportException {
Server server = new Server(8900);
server.run();
}
}
thrift提供各種服務(wù)監(jiān)聽服務(wù),包括傳統(tǒng)IO, New IO, Http方式. 還提供線程池的監(jiān)聽服務(wù)等。
下面是使用線程池的nio方式用法
注:在使用NIO時(shí),客戶端需要使用TFramedTransport,進(jìn)行數(shù)據(jù)傳輸
//客戶端代碼
public static LocalClient getClient(String ip,int port) throws TTransportException, IOException{
TSocket transport = new TSocket(ip,port);
TFramedTransport tt = new TFramedTransport(transport);
TProtocol protocol = new TBinaryProtocol(tt);
tt.open();
LocalClient client = new LocalClient(protocol, port, tt) ;
return client;
}
public static LocalClient getClient(String ip,int port) throws TTransportException, IOException{
TSocket transport = new TSocket(ip,port);
TFramedTransport tt = new TFramedTransport(transport);
TProtocol protocol = new TBinaryProtocol(tt);
tt.open();
LocalClient client = new LocalClient(protocol, port, tt) ;
return client;
}
//服務(wù)器端代碼
public Server(int _port) throws TTransportException{
this.port = _port;
Factory protoFactory = new TBinaryProtocol.Factory(true, true);
// TServerTransport serverTransport = new TServerSocket(port);
DemoService.Processor processor = new DemoService.Processor(this);
// tr_server = new TThreadPoolServer(new Args(serverTransport).processor(processor)
// .protocolFactory(protoFactory));
TNonblockingServerTransport nioTransport = new TNonblockingServerSocket(port);
tr_server = new TNonblockingServer(new Args(nioTransport).processor(processor)
.protocolFactory(protoFactory));
}
public Server(int _port) throws TTransportException{
this.port = _port;
Factory protoFactory = new TBinaryProtocol.Factory(true, true);
// TServerTransport serverTransport = new TServerSocket(port);
DemoService.Processor processor = new DemoService.Processor(this);
// tr_server = new TThreadPoolServer(new Args(serverTransport).processor(processor)
// .protocolFactory(protoFactory));
TNonblockingServerTransport nioTransport = new TNonblockingServerSocket(port);
tr_server = new TNonblockingServer(new Args(nioTransport).processor(processor)
.protocolFactory(protoFactory));
}
5. 下面就可以分別運(yùn)行 main方法,進(jìn)行測試即可。
Good Luck!
Yours Matthew!