Thrift入门及Java实例演示 | micmiu - 大大的技术 | 小小的生活
2013-02-21 16:03
405 查看
Thrift入门及Java实例演示
作者:概述
下载配置
基本概念数据类型
服务端编码基本步骤
客户端编码基本步骤
数据传输协议
实例演示(java)thrift生成代码
实现接口Iface
TSimpleServer服务模型
TThreadPoolServer服务模型
TNonblockingServer服务模型
THsHaServer服务模型
异步客户端
[一]、概述
Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在C++,Java,Python,PHP,Ruby,Erlang,Perl,Haskell,C#,Cocoa,JavaScript,Node.js,Smalltalk,andOCaml等等编程语言间无缝结合的、高效的服务。
Thrift最初由facebook开发,07年四月开放源码,08年5月进入apache孵化器。thrift允许你定义一个简单的定义文件中的数据类型和服务接口。以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。
官网地址:
推荐值得一看的文章:
到官网下载最新版本,截止今日(2012-06-11)最新版本为0.8.0.
1.如果是Maven构建项目的,直接在pom.xml中添加如下内容:
1 | < dependency > |
2 | < groupId >org.apache.thrift</ groupId > |
3 | < artifactId >libthrift</ artifactId > |
4 | < version >0.8.0</ version > |
5 | </ dependency > |
[三]、基本概念
1.数据类型
基本类型:bool:布尔值,true或false,对应Java的boolean
byte:8位有符号整数,对应Java的byte
i16:16位有符号整数,对应Java的short
i32:32位有符号整数,对应Java的int
i64:64位有符号整数,对应Java的long
double:64位浮点数,对应Java的double
string:utf-8编码的字符串,对应Java的String
结构体类型:struct:定义公共的对象,类似于C语言中的结构体定义,在Java中是一个JavaBean
容器类型:list:对应Java的ArrayList
set:对应Java的HashSet
map:对应Java的HashMap
异常类型:exception:对应Java的Exception
服务类型:service:对应服务的类
2.服务端编码基本步骤:
实现服务处理接口impl
创建TProcessor
创建TServerTransport
创建TProtocol
创建TServer
启动Server
3.客户端编码基本步骤:
创建Transport
创建TProtocol
基于TTransport和TProtocol创建Client
调用Client的相应方法
4.数据传输协议
TBinaryProtocol:二进制格式.
TCompactProtocol:压缩格式
TJSONProtocol:JSON格式
TSimpleJSONProtocol:提供JSON只写协议,生成的文件很容易通过脚本语言解析
tips:客户端和服务端的协议要一致
[四]、实例演示
1.thrift生成代码
创建Thrift文件:G:\test\thrift\demoHello.thrift,内容如下:
1 | namespacejavacom.micmiu.thrift.demo |
2 |
3 | serviceHelloWorldService{ |
4 | stringsayHello(1:stringusername) |
5 | } |
G:\test\thrift>tree/F 卷other的文件夹PATH列表 卷序列号为D238-BE47 G:. demoHello.thrift demouser.thrift thrift-0.8.0.exe 没有子文件夹thrift-0.8.0.exe是官网提供的windows下编译工具,运用这个工具生成相关代码:
1 | thrift-0.8.0.exe-r-genjava./demoHello.thrift |
G:\test\thrift>tree/F将生成的HelloWorldService.java文件copy到自己测试的工程中,我的工程是用maven构建的,故在pom.xml中增加如下内容:
卷other的文件夹PATH列表
卷序列号为D238-BE47
G:.
│demoHello.thrift
│demouser.thrift
│thrift-0.8.0.exe
│
└─gen-java
└─com
└─micmiu
└─thrift
└─demo
HelloWorldService.java
1 | < dependency > |
2 | < groupId >org.apache.thrift</ groupId > |
3 | < artifactId >libthrift</ artifactId > |
4 | < version >0.8.0</ version > |
5 | </ dependency > |
6 | < dependency > |
7 | < groupId >org.slf4j</ groupId > |
8 | < artifactId >slf4j-log4j12</ artifactId > |
9 | < version >1.5.8</ version > |
10 | </ dependency > |
java代码:HelloWorldImpl.java
1 | package com.micmiu.thrift.demo; |
2 |
3 | import org.apache.thrift.TException; |
4 |
5 | /** |
6 | *blog |
7 | * |
8 | *@authorMichael |
9 | * |
10 | */ |
11 | public class HelloWorldImpl implements HelloWorldService.Iface{ |
12 |
13 | public HelloWorldImpl(){ |
14 | } |
15 |
16 | @Override |
17 | public StringsayHello(Stringusername) throws TException{ |
18 | return "Hi," +username+ "welcometomyblogwww.micmiu.com" ; |
19 | } |
20 |
21 | } |
简单的单线程服务模型,一般用于测试。
编写服务端server代码:HelloServerDemo.java
1 | package com.micmiu.thrift.demo; |
2 |
3 | import org.apache.thrift.TProcessor; |
4 | import org.apache.thrift.protocol.TBinaryProtocol; |
5 | import org.apache.thrift.protocol.TCompactProtocol; |
6 | import org.apache.thrift.protocol.TJSONProtocol; |
7 | import org.apache.thrift.protocol.TSimpleJSONProtocol; |
8 | import org.apache.thrift.server.TServer; |
9 | import org.apache.thrift.server.TSimpleServer; |
10 | import org.apache.thrift.transport.TServerSocket; |
11 |
12 | /** |
13 | *blog |
14 | * |
15 | *@authorMichael |
16 | * |
17 | */ |
18 | public class HelloServerDemo{ |
19 | public static final int SERVER_PORT= 8090 ; |
20 |
21 | public void startServer(){ |
22 | try { |
23 | System.out.println( "HelloWorldTSimpleServerstart...." ); |
24 |
25 | TProcessortprocessor= new HelloWorldService.Processor<HelloWorldService.Iface>( |
26 | new HelloWorldImpl()); |
27 | //HelloWorldService.Processor<HelloWorldService.Iface>tprocessor= |
28 | //newHelloWorldService.Processor<HelloWorldService.Iface>( |
29 | //newHelloWorldImpl()); |
30 |
31 | //简单的单线程服务模型,一般用于测试 |
32 | TServerSocketserverTransport= new TServerSocket(SERVER_PORT); |
33 | TServer.ArgstArgs= new TServer.Args(serverTransport); |
34 | tArgs.processor(tprocessor); |
35 | tArgs.protocolFactory( new TBinaryProtocol.Factory()); |
36 | //tArgs.protocolFactory(newTCompactProtocol.Factory()); |
37 | //tArgs.protocolFactory(newTJSONProtocol.Factory()); |
38 | TServerserver= new TSimpleServer(tArgs); |
39 | server.serve(); |
40 |
41 | } catch (Exceptione){ |
42 | System.out.println( "Serverstarterror!!!" ); |
43 | e.printStackTrace(); |
44 | } |
45 | } |
46 |
47 | /** |
48 | *@paramargs |
49 | */ |
50 | public static void main(String[]args){ |
51 | HelloServerDemoserver= new HelloServerDemo(); |
52 | server.startServer(); |
53 | } |
54 |
55 | } |
1 | package com.micmiu.thrift.demo; |
2 |
3 | import org.apache.thrift.TException; |
4 | import org.apache.thrift.protocol.TBinaryProtocol; |
5 | import org.apache.thrift.protocol.TCompactProtocol; |
6 | import org.apache.thrift.protocol.TJSONProtocol; |
7 | import org.apache.thrift.protocol.TProtocol; |
8 | import org.apache.thrift.transport.TSocket; |
9 | import org.apache.thrift.transport.TTransport; |
10 | import org.apache.thrift.transport.TTransportException; |
11 |
12 | /** |
13 | *blog |
14 | * |
15 | *@authorMichael |
16 | * |
17 | */ |
18 | public class HelloClientDemo{ |
19 |
20 | public static final StringSERVER_IP= "localhost" ; |
21 | public static final int SERVER_PORT= 8090 ; |
22 | public static final int TIMEOUT= 30000 ; |
23 |
24 | /** |
25 | * |
26 | *@paramuserName |
27 | */ |
28 | public void startClient(StringuserName){ |
29 | TTransporttransport= null ; |
30 | try { |
31 | transport= new TSocket(SERVER_IP,SERVER_PORT,TIMEOUT); |
32 | //协议要和服务端一致 |
33 | TProtocolprotocol= new TBinaryProtocol(transport); |
34 | //TProtocolprotocol=newTCompactProtocol(transport); |
35 | //TProtocolprotocol=newTJSONProtocol(transport); |
36 | HelloWorldService.Clientclient= new HelloWorldService.Client( |
37 | protocol); |
38 | transport.open(); |
39 | Stringresult=client.sayHello(userName); |
40 | System.out.println( "Thrifyclientresult=:" +result); |
41 | } catch (TTransportExceptione){ |
42 | e.printStackTrace(); |
43 | } catch (TExceptione){ |
44 | e.printStackTrace(); |
45 | } finally { |
46 | if ( null !=transport){ |
47 | transport.close(); |
48 | } |
49 | } |
50 | } |
51 |
52 | /** |
53 | *@paramargs |
54 | */ |
55 | public static void main(String[]args){ |
56 | HelloClientDemoclient= new HelloClientDemo(); |
57 | client.startClient( "Michael" ); |
58 |
59 | } |
60 |
61 | } |
HelloWorldTSimpleServerstart....再运行客户端调用程序,日志如下:
Thrifyclientresult=:Hi,Michaelwelcometomyblogwww.micmiu.com测试成功,和预期的返回信息一致。
4.TThreadPoolServer服务模型
线程池服务模型,使用标准的阻塞式IO,预先创建一组线程处理请求。
编写服务端代码:HelloServerDemo.java
1 | package com.micmiu.thrift.demo; |
2 |
3 | import org.apache.thrift.TProcessor; |
4 | import org.apache.thrift.protocol.TBinaryProtocol; |
5 | import org.apache.thrift.server.TServer; |
6 | import org.apache.thrift.server.TThreadPoolServer; |
7 | import org.apache.thrift.transport.TServerSocket; |
8 |
9 | /** |
10 | *blog |
11 | * |
12 | *@authorMichael |
13 | * |
14 | */ |
15 | public class HelloServerDemo{ |
16 | public static final int SERVER_PORT= 8090 ; |
17 |
18 | public void startServer(){ |
19 | try { |
20 | System.out.println( "HelloWorldTThreadPoolServerstart...." ); |
21 |
22 | TProcessortprocessor= new HelloWorldService.Processor<HelloWorldService.Iface>( |
23 | new HelloWorldImpl()); |
24 |
25 | TServerSocketserverTransport= new TServerSocket(SERVER_PORT); |
26 | TThreadPoolServer.ArgsttpsArgs= new TThreadPoolServer.Args( |
27 | serverTransport); |
28 | ttpsArgs.processor(tprocessor); |
29 | ttpsArgs.protocolFactory( new TBinaryProtocol.Factory()); |
30 |
31 | //线程池服务模型,使用标准的阻塞式IO,预先创建一组线程处理请求。 |
32 | TServerserver= new TThreadPoolServer(ttpsArgs); |
33 | server.serve(); |
34 |
35 | } catch (Exceptione){ |
36 | System.out.println( "Serverstarterror!!!" ); |
37 | e.printStackTrace(); |
38 | } |
39 | } |
40 |
41 | /** |
42 | *@paramargs |
43 | */ |
44 | public static void main(String[]args){ |
45 | HelloServerDemoserver= new HelloServerDemo(); |
46 | server.startServer(); |
47 | } |
48 |
49 | } |
Thrifyclientresult=:Hi,Michaelwelcometomyblogwww.micmiu.com5.TNonblockingServer服务模型
使用非阻塞式IO,服务端和客户端需要指定TFramedTransport数据传输的方式。
编写服务端代码:HelloServerDemo.java
1 | package com.micmiu.thrift.demo; |
2 |
3 | import org.apache.thrift.TProcessor; |
4 | import org.apache.thrift.protocol.TCompactProtocol; |
5 | import org.apache.thrift.server.TNonblockingServer; |
6 | import org.apache.thrift.server.TServer; |
7 | import org.apache.thrift.transport.TFramedTransport; |
8 | import org.apache.thrift.transport.TNonblockingServerSocket; |
9 |
10 | /** |
11 | *blog |
12 | * |
13 | *@authorMichael |
14 | * |
15 | */ |
16 | public class HelloServerDemo{ |
17 | public static final int SERVER_PORT= 8090 ; |
18 |
19 | public void startServer(){ |
20 | try { |
21 | System.out.println( "HelloWorldTNonblockingServerstart...." ); |
22 |
23 | TProcessortprocessor= new HelloWorldService.Processor<HelloWorldService.Iface>( |
24 | new HelloWorldImpl()); |
25 |
26 | TNonblockingServerSockettnbSocketTransport= new TNonblockingServerSocket( |
27 | SERVER_PORT); |
28 | TNonblockingServer.ArgstnbArgs= new TNonblockingServer.Args( |
29 | tnbSocketTransport); |
30 | tnbArgs.processor(tprocessor); |
31 | tnbArgs.transportFactory( new TFramedTransport.Factory()); |
32 | tnbArgs.protocolFactory( new TCompactProtocol.Factory()); |
33 |
34 | //使用非阻塞式IO,服务端和客户端需要指定TFramedTransport数据传输的方式 |
35 | TServerserver= new TNonblockingServer(tnbArgs); |
36 | server.serve(); |
37 |
38 | } catch (Exceptione){ |
39 | System.out.println( "Serverstarterror!!!" ); |
40 | e.printStackTrace(); |
41 | } |
42 | } |
43 |
44 | /** |
45 | *@paramargs |
46 | */ |
47 | public static void main(String[]args){ |
48 | HelloServerDemoserver= new HelloServerDemo(); |
49 | server.startServer(); |
50 | } |
51 |
52 | } |
1 | package com.micmiu.thrift.demo; |
2 |
3 | import org.apache.thrift.TException; |
4 | import org.apache.thrift.protocol.TCompactProtocol; |
5 | import org.apache.thrift.protocol.TProtocol; |
6 | import org.apache.thrift.transport.TFramedTransport; |
7 | import org.apache.thrift.transport.TSocket; |
8 | import org.apache.thrift.transport.TTransport; |
9 | import org.apache.thrift.transport.TTransportException; |
10 |
11 | /** |
12 | *blog |
13 | * |
14 | *@authorMichael |
15 | * |
16 | */ |
17 | public class HelloClientDemo{ |
18 |
19 | public static final StringSERVER_IP= "localhost" ; |
20 | public static final int SERVER_PORT= 8090 ; |
21 | public static final int TIMEOUT= 30000 ; |
22 |
23 | /** |
24 | * |
25 | *@paramuserName |
26 | */ |
27 | public void startClient(StringuserName){ |
28 | TTransporttransport= null ; |
29 | try { |
30 | transport= new TFramedTransport( new TSocket(SERVER_IP, |
31 | SERVER_PORT,TIMEOUT)); |
32 | //协议要和服务端一致 |
33 | TProtocolprotocol= new TCompactProtocol(transport); |
34 | HelloWorldService.Clientclient= new HelloWorldService.Client( |
35 | protocol); |
36 | transport.open(); |
37 | Stringresult=client.sayHello(userName); |
38 | System.out.println( "Thrifyclientresult=:" +result); |
39 | } catch (TTransportExceptione){ |
40 | e.printStackTrace(); |
41 | } catch (TExceptione){ |
42 | e.printStackTrace(); |
43 | } finally { |
44 | if ( null !=transport){ |
45 | transport.close(); |
46 | } |
47 | } |
48 | } |
49 |
50 | /** |
51 | *@paramargs |
52 | */ |
53 | public static void main(String[]args){ |
54 | HelloClientDemoclient= new HelloClientDemo(); |
55 | client.startClient( "Michael" ); |
56 |
57 | } |
58 |
59 | } |
Thrifyclientresult=:Hi,Michaelwelcometomyblogwww.micmiu.com6.THsHaServer服务模型
半同步半异步的服务端模型,需要指定为:TFramedTransport数据传输的方式。
编写服务端代码:HelloServerDemo.java
1 | package com.micmiu.thrift.demo; |
2 |
3 | import org.apache.thrift.TProcessor; |
4 | import org.apache.thrift.protocol.TBinaryProtocol; |
5 | import org.apache.thrift.protocol.TCompactProtocol; |
6 | import org.apache.thrift.server.THsHaServer; |
7 | import org.apache.thrift.server.TNonblockingServer; |
8 | import org.apache.thrift.server.TServer; |
9 | import org.apache.thrift.server.TSimpleServer; |
10 | import org.apache.thrift.server.TThreadPoolServer; |
11 | import org.apache.thrift.transport.TFramedTransport; |
12 | import org.apache.thrift.transport.TNonblockingServerSocket; |
13 | import org.apache.thrift.transport.TServerSocket; |
14 |
15 | /** |
16 | *blog |
17 | * |
18 | *@authorMichael |
19 | * |
20 | */ |
21 | public class HelloServerDemo{ |
22 | public static final int SERVER_PORT= 8090 ; |
23 |
24 | public void startServer(){ |
25 | try { |
26 | System.out.println( "HelloWorldTHsHaServerstart...." ); |
27 |
28 | TProcessortprocessor= new HelloWorldService.Processor<HelloWorldService.Iface>( |
29 | new HelloWorldImpl()); |
30 |
31 | TNonblockingServerSockettnbSocketTransport= new TNonblockingServerSocket( |
32 | SERVER_PORT); |
33 | THsHaServer.ArgsthhsArgs= new THsHaServer.Args(tnbSocketTransport); |
34 | thhsArgs.processor(tprocessor); |
35 | thhsArgs.transportFactory( new TFramedTransport.Factory()); |
36 | thhsArgs.protocolFactory( new TBinaryProtocol.Factory()); |
37 |
38 | //半同步半异步的服务模型 |
39 | TServerserver= new THsHaServer(thhsArgs); |
40 | server.serve(); |
41 |
42 | } catch (Exceptione){ |
43 | System.out.println( "Serverstarterror!!!" ); |
44 | e.printStackTrace(); |
45 | } |
46 | } |
47 |
48 | /** |
49 | *@paramargs |
50 | */ |
51 | public static void main(String[]args){ |
52 | HelloServerDemoserver= new HelloServerDemo(); |
53 | server.startServer(); |
54 | } |
55 |
56 | } |
7.异步客户端
编写服务端代码:HelloServerDemo.java
1 | package com.micmiu.thrift.demo; |
2 |
3 | import org.apache.thrift.TProcessor; |
4 | import org.apache.thrift.protocol.TCompactProtocol; |
5 | import org.apache.thrift.server.TNonblockingServer; |
6 | import org.apache.thrift.server.TServer; |
7 | import org.apache.thrift.transport.TFramedTransport; |
8 | import org.apache.thrift.transport.TNonblockingServerSocket; |
9 |
10 | /** |
11 | *blog |
12 | * |
13 | *@authorMichael |
14 | * |
15 | */ |
16 | public class HelloServerDemo{ |
17 | public static final int SERVER_PORT= 8090 ; |
18 |
19 | public void startServer(){ |
20 | try { |
21 | System.out.println( "HelloWorldTNonblockingServerstart...." ); |
22 |
23 | TProcessortprocessor= new HelloWorldService.Processor<HelloWorldService.Iface>( |
24 | new HelloWorldImpl()); |
25 |
26 | TNonblockingServerSockettnbSocketTransport= new TNonblockingServerSocket( |
27 | SERVER_PORT); |
28 | TNonblockingServer.ArgstnbArgs= new TNonblockingServer.Args( |
29 | tnbSocketTransport); |
30 | tnbArgs.processor(tprocessor); |
31 | tnbArgs.transportFactory( new TFramedTransport.Factory()); |
32 | tnbArgs.protocolFactory( new TCompactProtocol.Factory()); |
33 |
34 | //使用非阻塞式IO,服务端和客户端需要指定TFramedTransport数据传输的方式 |
35 | TServerserver= new TNonblockingServer(tnbArgs); |
36 | server.serve(); |
37 |
38 | } catch (Exceptione){ |
39 | System.out.println( "Serverstarterror!!!" ); |
40 | e.printStackTrace(); |
41 | } |
42 | } |
43 |
44 | /** |
45 | *@paramargs |
46 | */ |
47 | public static void main(String[]args){ |
48 | HelloServerDemoserver= new HelloServerDemo(); |
49 | server.startServer(); |
50 | } |
51 |
52 | } |
1 | package com.micmiu.thrift.demo; |
2 |
3 | import java.util.concurrent.CountDownLatch; |
4 | import java.util.concurrent.TimeUnit; |
5 |
6 | import org.apache.thrift.TException; |
7 | import org.apache.thrift.async.AsyncMethodCallback; |
8 | import org.apache.thrift.async.TAsyncClientManager; |
9 | import org.apache.thrift.protocol.TCompactProtocol; |
10 | import org.apache.thrift.protocol.TProtocolFactory; |
11 | import org.apache.thrift.transport.TNonblockingSocket; |
12 | import org.apache.thrift.transport.TNonblockingTransport; |
13 |
14 | import com.micmiu.thrift.demo.HelloWorldService.AsyncClient.sayHello_call; |
15 |
16 | /** |
17 | *blog |
18 | * |
19 | *@authorMichael |
20 | * |
21 | */ |
22 | public class HelloAsynClientDemo{ |
23 |
24 | public static final StringSERVER_IP= "localhost" ; |
25 | public static final int SERVER_PORT= 8090 ; |
26 | public static final int TIMEOUT= 30000 ; |
27 |
28 | /** |
29 | * |
30 | *@paramuserName |
31 | */ |
32 | public void startClient(StringuserName){ |
33 | try { |
34 | TAsyncClientManagerclientManager= new TAsyncClientManager(); |
35 | TNonblockingTransporttransport= new TNonblockingSocket(SERVER_IP, |
36 | SERVER_PORT,TIMEOUT); |
37 |
38 | TProtocolFactorytprotocol= new TCompactProtocol.Factory(); |
39 | HelloWorldService.AsyncClientasyncClient= new HelloWorldService.AsyncClient( |
40 | tprotocol,clientManager,transport); |
41 | System.out.println( "Clientstart....." ); |
42 |
43 | CountDownLatchlatch= new CountDownLatch( 1 ); |
44 | AsynCallbackcallBack= new AsynCallback(latch); |
45 | System.out.println( "callmethodsayHellostart..." ); |
46 | asyncClient.sayHello(userName,callBack); |
47 | System.out.println( "callmethodsayHello....end" ); |
48 | boolean wait=latch.await( 30 ,TimeUnit.SECONDS); |
49 | System.out.println( "latch.await=:" +wait); |
50 | } catch (Exceptione){ |
51 | e.printStackTrace(); |
52 | } |
53 | System.out.println( "startClientend." ); |
54 | } |
55 |
56 | public class AsynCallback implements AsyncMethodCallback<sayHello_call>{ |
57 | private CountDownLatchlatch; |
58 |
59 | public AsynCallback(CountDownLatchlatch){ |
60 | this .latch=latch; |
61 | } |
62 |
63 | @Override |
64 | public void onComplete(sayHello_callresponse){ |
65 | System.out.println( "onComplete" ); |
66 | try { |
67 | //Thread.sleep(1000L*1); |
68 | System.out.println( "AsynCallresult=:" |
69 | +response.getResult().toString()); |
70 | } catch (TExceptione){ |
71 | e.printStackTrace(); |
72 | } catch (Exceptione){ |
73 | e.printStackTrace(); |
74 | } finally { |
75 | latch.countDown(); |
76 | } |
77 | } |
78 |
79 | @Override |
80 | public void onError(Exceptionexception){ |
81 | System.out.println( "onError:" +exception.getMessage()); |
82 | latch.countDown(); |
83 | } |
84 | } |
85 |
86 | /** |
87 | *@paramargs |
88 | */ |
89 | public static void main(String[]args){ |
90 | HelloAsynClientDemoclient= new HelloAsynClientDemo(); |
91 | client.startClient( "Michael" ); |
92 |
93 | } |
94 |
95 | } |
Clientstart.....————
callmethodsayHellostart...
callmethodsayHello....end
onComplete
AsynCallresult=:Hi,Michaelwelcometomyblogwww.micmiu.com
latch.await=:true
startClientend.
相关文章推荐
- Thrift入门及Java实例演示 | micmiu - 大大的技术 | 小小的生活
- Thrift入门及Java实例演示
- Thrift入门及Java实例演示
- Thrift入门及Java实例演示【转】
- Thrift入门及Java实例演示
- Thrift入门及Java实例演示
- Thrift入门及Java实例演示
- Thrift入门及Java实例演示
- Thrift入门及Java实例演示
- Thrift入门及Java实例演示
- Thrift入门及Java实例演示
- [置顶] Thrift入门及Java实例演示
- Thrift入门及Java实例演示
- Apache Thrift学习之一(入门及Java实例演示)
- Thrift入门及Java实例演示
- Thrift入门及Java实例演示
- Thrift入门及Java实例演示
- Thrift入门及Java实例演示
- Thrift入门及Java实例演示
- Thrift入门及Java实例演示