您的位置:首页 > 编程语言 > Java开发

Thrift入门及Java实例演示 | micmiu - 大大的技术 | 小小的生活

2013-02-21 16:03 405 查看
Thrift入门及Java实例演示|micmiu-大大的技术|小小的生活

Thrift入门及Java实例演示

作者:Michael日期: 2012年6月14日发表评论(10)查看评论目录:

概述
下载配置

基本概念数据类型
服务端编码基本步骤

客户端编码基本步骤

数据传输协议

实例演示(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客户端和服务器通信的无缝跨编程语言。

官网地址:thrift.apache.org

推荐值得一看的文章:

http://jnb.ociweb.com/jnb/jnbJun2009.html

http://wiki.apache.org/thrifthttp://thrift.apache.org/static/files/thrift-20070401.pdf[二]、下载配置

到官网下载最新版本,截止今日(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
>
2.如果自己编译lib包,把下载的压缩包解压到X:盘,然后在X:\thrift-0.8.0\lib\java目录下运行ant进行自动编译,会在X:\thrift-0.8.0\lib\java\build\目录下看到编译好的lib包:libthrift-0.8.0.jar

[三]、基本概念

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
卷other的文件夹PATH列表
卷序列号为D238-BE47
G:.
│demoHello.thrift
│demouser.thrift
│thrift-0.8.0.exe

└─gen-java
└─com
└─micmiu
└─thrift
└─demo
HelloWorldService.java
将生成的HelloWorldService.java文件copy到自己测试的工程中,我的工程是用maven构建的,故在pom.xml中增加如下内容:

查看源代码打印帮助
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
>
2.实现接口Iface

java代码:HelloWorldImpl.java

查看源代码打印帮助
1
package
com.micmiu.thrift.demo;
2
3
import
org.apache.thrift.TException;
4
5
/**
6
*bloghttp://www.micmiu.com
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
}
3.TSimpleServer服务端

简单的单线程服务模型,一般用于测试。

编写服务端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
*bloghttp://www.micmiu.com
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
}
编写客户端Client代码:HelloClientDemo.java

查看源代码打印帮助
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
*bloghttp://www.micmiu.com
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
*bloghttp://www.micmiu.com
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
}
客户端Client代码和之前的一样,只要数据传输的协议一致即可,客户端测试成功,结果如下:

Thrifyclientresult=:Hi,Michaelwelcometomyblogwww.micmiu.com
5.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
*bloghttp://www.micmiu.com
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
}
编写客户端代码:HelloClientDemo.java

查看源代码打印帮助
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
*bloghttp://www.micmiu.com
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.com
6.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
*bloghttp://www.micmiu.com
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
}
客户端代码和上面4中的类似,只要注意传输协议一致以及指定传输方式为TFramedTransport。

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
*bloghttp://www.micmiu.com
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
}
编写客户端Client代码:HelloAsynClientDemo.java

查看源代码打印帮助
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
*bloghttp://www.micmiu.com
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.
————

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
章节导航