java thrift 生成java的service什么意识

IBM Bluemix
点击按钮,开始云上的开发!
developerWorks 社区
Apache Thrift 是 Facebook 实现的一种高效的、支持多种编程语言的远程服务调用的框架。本文将从 Java 开发人员角度详细介绍 Apache Thrift 的架构、开发和部署,并且针对不同的传输协议和服务类型给出相应的 Java 实例,同时详细介绍 Thrift 异步客户端的实现,最后提出使用 Thrift 需要注意的事项。
黄晓军,湖南大学信息科学与工程学院在读研究生,2011 年 5 月至 2011 年 9 月 IBM CDL实习,关注云计算等。
, 软件工程师, IBM
张静,IBM 中国软件实验室(CSDL BJ)China Emerging Technology Institute 成员,曾参与 Hyperservice, Database as Service, SaaS Development Environment项目的开发。主要的关注点在 Web 2.0 的领域数据建模、查询与访问, 数据库云计算,SaaS等
, 高级软件工程师,
张凯,IBM中国研发中心高级软件工程师。从事 WebSphere 业务集成和业务流程管理相关产品研发,以及 CDL 新技术研究院云计算孵化项目研究。他对基于语义的信息检索,搜索引擎,Web 2.0,SOA,云计算和移动互联网应用很感兴趣。
前言:目前流行的服务调用方式有很多种,例如基于 SOAP 消息格式的 Web Service,基于 JSON 消息格式的 RESTful 服务等。其中所用到的数据传输方式包括 XML,JSON 等,然而 XML 相对体积太大,传输效率低,JSON 体积较小,新颖,但还不够完善。本文将介绍由 Facebook 开发的远程服务调用框架 Apache Thrift,它采用接口描述语言定义并创建服务,支持可扩展的跨语言服务开发,所包含的代码生成引擎可以在多种语言中,如 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk 等创建高效的、无缝的服务,其传输数据采用二进制格式,相对 XML 和 JSON 体积更小,对于高并发、大数据量和多语言的环境更有优势。本文将详细介绍 Thrift 的使用,并且提供丰富的实例代码加以解释说明,帮助使用者快速构建服务。一个简单的 Thrift 实例本文首先介绍一个简单的 Thrift 实现实例,使读者能够快速直观地了解什么是 Thrift 以及如何使用 Thrift 构建服务。创建一个简单的服务 Hello。首先根据 Thrift 的语法规范编写脚本文件 Hello.thrift,代码如下:清单 1. Hello.thrift namespace java service.demo
service Hello{
string helloString(1:string para)
i32 helloInt(1:i32 para)
bool helloBoolean(1:bool para)
void helloVoid()
string helloNull()
}其中定义了服务 Hello 的五个方法,每个方法包含一个方法名,参数列表和返回类型。每个参数包括参数序号,参数类型以及参数名。
Thrift 是对 IDL(Interface Definition Language) 描述性语言的一种具体实现。因此,以上的服务描述文件使用 IDL 语法编写。使用 Thrift 工具编译 Hello.thrift,就会生成相应的 Hello.java 文件。该文件包含了在 Hello.thrift 文件中描述的服务 Hello 的接口定义,即 Hello.Iface 接口,以及服务调用的底层通信细节,包括客户端的调用逻辑 Hello.Client 以及服务器端的处理逻辑 Hello.Processor,用于构建客户端和服务器端的功能。
创建 HelloServiceImpl.java 文件并实现 Hello.java 文件中的 Hello.Iface 接口,代码如下:清单 2. HelloServiceImpl.java package service.
import org.apache.thrift.TE
public class HelloServiceImpl implements Hello.Iface {
public boolean helloBoolean(boolean para) throws TException {
public int helloInt(int para) throws TException {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
public String helloNull() throws TException {
public String helloString(String para) throws TException {
public void helloVoid() throws TException {
System.out.println("Hello World");
}创建服务器端实现代码,将 HelloServiceImpl 作为具体的处理器传递给 Thrift 服务器,代码如下:清单 3. HelloServiceServer.java package service.
import org.apache.thrift.TP
import org.apache.thrift.protocol.TBinaryP
import org.apache.thrift.protocol.TBinaryProtocol.F
import org.apache.thrift.server.TS
import org.apache.thrift.server.TThreadPoolS
import org.apache.thrift.transport.TServerS
import org.apache.thrift.transport.TTransportE
import service.demo.H
import service.demo.HelloServiceI
public class HelloServiceServer {
* 启动 Thrift 服务器
* @param args
public static void main(String[] args) {
// 设置服务端口为 7911
TServerSocket serverTransport = new TServerSocket(7911);
// 设置协议工厂为 TBinaryProtocol.Factory
Factory proFactory = new TBinaryProtocol.Factory();
// 关联处理器与 Hello 服务的实现
TProcessor processor = new Hello.Processor(new HelloServiceImpl());
TServer server = new TThreadPoolServer(processor, serverTransport,
proFactory);
System.out.println("Start server on port 7911...");
server.serve();
} catch (TTransportException e) {
e.printStackTrace();
}创建客户端实现代码,调用 Hello.client 访问服务端的逻辑实现,代码如下:清单 4. HelloServiceClient.java package service.
import org.apache.thrift.TE
import org.apache.thrift.protocol.TBinaryP
import org.apache.thrift.protocol.TP
import org.apache.thrift.transport.TS
import org.apache.thrift.transport.TT
import org.apache.thrift.transport.TTransportE
import service.demo.H
public class HelloServiceClient {
* 调用 Hello 服务
* @param args
public static void main(String[] args) {
// 设置调用的服务地址为本地,端口为 7911
TTransport transport = new TSocket("localhost", 7911);
transport.open();
// 设置传输协议为 TBinaryProtocol
TProtocol protocol = new TBinaryProtocol(transport);
Hello.Client client = new Hello.Client(protocol);
// 调用服务的 helloVoid 方法
client.helloVoid();
transport.close();
} catch (TTransportException e) {
e.printStackTrace();
} catch (TException e) {
e.printStackTrace();
}代码编写完后运行服务器,再启动客户端调用服务 Hello 的方法 helloVoid,在服务器端的控制台窗口输出“Hello World”(helloVoid 方法实现在控制台打印字符串,没有返回值,所以客户端调用方法后没有返回值输出,读者可以自己尝试其他有返回值方法的调用,其结果可以打印在客户端的控制台窗口 )。Thrift 架构Thrift 包含一个完整的堆栈结构用于构建客户端和服务器端。下图描绘了 Thrift 的整体架构。图 1. 架构图如图所示,图中黄色部分是用户实现的业务逻辑,褐色部分是根据 Thrift 定义的服务接口描述文件生成的客户端和服务器端代码框架,红色部分是根据 Thrift 文件生成代码实现数据的读写操作。红色部分以下是 Thrift 的传输体系、协议以及底层 I/O 通信,使用 Thrift 可以很方便的定义一个服务并且选择不同的传输协议和传输层而不用重新生成代码。Thrift 服务器包含用于绑定协议和传输层的基础架构,它提供阻塞、非阻塞、单线程和多线程的模式运行在服务器上,可以配合服务器 / 容器一起运行,可以和现有的 J2EE 服务器 /Web 容器无缝的结合。服务端和客户端具体的调用流程如下:图 2. Server 端启动、服务时序图()该图所示是 HelloServiceServer 启动的过程以及服务被客户端调用时,服务器的响应过程。从图中我们可以看到,程序调用了 TThreadPoolServer 的 serve 方法后,server 进入阻塞监听状态,其阻塞在 TServerSocket 的 accept 方法上。当接收到来自客户端的消息后,服务器发起一个新线程处理这个消息请求,原线程再次进入阻塞状态。在新线程中,服务器通过 TBinaryProtocol 协议读取消息内容,调用 HelloServiceImpl 的 helloVoid 方法,并将结果写入 helloVoid_result 中传回客户端。图 3. Client 端调用服务时序图()该图所示是 HelloServiceClient 调用服务的过程以及接收到服务器端的返回值后处理结果的过程。从图中我们可以看到,程序调用了 Hello.Client 的 helloVoid 方法,在 helloVoid 方法中,通过 send_helloVoid 方法发送对服务的调用请求,通过 recv_helloVoid 方法接收服务处理请求后返回的结果。数据类型Thrift 脚本可定义的数据类型包括以下几种类型:
基本类型:
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:未知编码文本或二进制字符串,对应 Java 的 String
结构体类型:
struct:定义公共的对象,类似于 C 语言中的结构体定义,在 Java 中是一个 JavaBean
容器类型:
list:对应 Java 的 ArrayList
set:对应 Java 的 HashSet
map:对应 Java 的 HashMap
异常类型:
exception:对应 Java 的 Exception
服务类型:
service:对应服务的类协议Thrift 可以让用户选择客户端与服务端之间传输通信协议的类别,在传输协议上总体划分为文本 (text) 和二进制 (binary) 传输协议,为节约带宽,提高传输效率,一般情况下使用二进制类型的传输协议为多数,有时还会使用基于文本类型的协议,这需要根据项目 / 产品中的实际需求。常用协议有以下几种:
TBinaryProtocol —— 二进制编码格式进行数据传输
使用方法如清单 3 和清单 4 所示。
TCompactProtocol —— 高效率的、密集的二进制编码格式进行数据传输
构建 TCompactProtocol 协议的服务器和客户端只需替换清单 3 和清单 4 中 TBinaryProtocol 协议部分即可,替换成如下代码:清单 5. 使用 TCompactProtocol 协议构建的 HelloServiceServer.java TCompactProtocol.Factory proFactory = new TCompactProtocol.Factory();清单 6. 使用 TCompactProtocol 协议的 HelloServiceClient.java TCompactProtocol protocol = new TCompactProtocol(transport);
TJSONProtocol —— 使用 JSON 的数据编码协议进行数据传输
构建 TJSONProtocol 协议的服务器和客户端只需替换清单 3 和清单 4 中 TBinaryProtocol 协议部分即可,替换成如下代码:清单 7. 使用 TJSONProtocol 协议构建的 HelloServiceServer.java TJSONProtocol.Factory proFactory = new TJSONProtocol.Factory();清单 8. 使用 TJSONProtocol 协议的 HelloServiceClient.java TJSONProtocol protocol = new TJSONProtocol(transport);
TSimpleJSONProtocol —— 只提供 JSON 只写的协议,适用于通过脚本语言解析传输层常用的传输层有以下几种:
TSocket —— 使用阻塞式 I/O 进行传输,是最常见的模式
使用方法如清单 4 所示。
TFramedTransport —— 使用非阻塞方式,按块的大小进行传输,类似于 Java 中的 NIO
若使用 TFramedTransport 传输层,其服务器必须修改为非阻塞的服务类型,客户端只需替换清单 4 中 TTransport 部分,代码如下,清单 9 中 TNonblockingServerTransport 类是构建非阻塞 socket 的抽象类,TNonblockingServerSocket 类继承 TNonblockingServerTransport清单 9. 使用 TFramedTransport 传输层构建的 HelloServiceServer.java TNonblockingServerTransport serverT
serverTransport = new TNonblockingServerSocket(10005);
Hello.Processor processor = new Hello.Processor(new HelloServiceImpl());
TServer server = new TNonblockingServer(processor, serverTransport);
System.out.println("Start server on port 10005 ...");
server.serve();清单 10. 使用 TFramedTransport 传输层的 HelloServiceClient.java TTransport transport = new TFramedTransport(new TSocket("localhost", 10005));
TNonblockingTransport —— 使用非阻塞方式,用于构建异步客户端
使用方法请参考 Thrift 异步客户端构建服务端类型常见的服务端类型有以下几种:
TSimpleServer —— 单线程服务器端使用标准的阻塞式 I/O
代码如下:清单 11. 使用 TSimpleServer 服务端构建的 HelloServiceServer.java TServerSocket serverTransport = new TServerSocket(7911);
TProcessor processor = new Hello.Processor(new HelloServiceImpl());
TServer server = new TSimpleServer(processor, serverTransport);
System.out.println("Start server on port 7911...");
server.serve();客户端的构建方式可参考清单 4。
TThreadPoolServer —— 多线程服务器端使用标准的阻塞式 I/O
使用方法如清单 3 所示。
TNonblockingServer —— 多线程服务器端使用非阻塞式 I/O
使用方法请参考 Thrift 异步客户端构建Thrift 异步客户端构建Thrift 提供非阻塞的调用方式,可构建异步客户端。在这种方式中,Thrift 提供了新的类 TAsyncClientManager 用于管理客户端的请求,在一个线程上追踪请求和响应,同时通过接口 AsyncClient 传递标准的参数和 callback 对象,服务调用完成后,callback 提供了处理调用结果和异常的方法。首先我们看 callback 的实现:清单 12.CallBack 的实现:MethodCallback.java package service.
import org.apache.thrift.async.AsyncMethodC
public class MethodCallback implements AsyncMethodCallback {
Object response =
public Object getResult() {
// 返回结果值
return this.
// 处理服务返回的结果值
public void onComplete(Object response) {
this.response =
// 处理调用服务过程中出现的异常
public void onError(Throwable throwable) {
}如代码所示,onComplete 方法接收服务处理后的结果,此处我们将结果 response 直接赋值给 callback 的私有属性 response。onError 方法接收服务处理过程中抛出的异常,此处未对异常进行处理。创建非阻塞服务器端实现代码,将 HelloServiceImpl 作为具体的处理器传递给异步 Thrift 服务器,代码如下:清单 13.HelloServiceAsyncServer.java package service.
import org.apache.thrift.server.TNonblockingS
import org.apache.thrift.server.TS
import org.apache.thrift.transport.TNonblockingServerS
import org.apache.thrift.transport.TNonblockingServerT
import org.apache.thrift.transport.TTransportE
import service.demo.H
import service.demo.HelloServiceI
public class HelloServiceAsyncServer {
* 启动 Thrift 异步服务器
* @param args
public static void main(String[] args) {
TNonblockingServerTransport serverT
serverTransport = new TNonblockingServerSocket(10005);
Hello.Processor processor = new Hello.Processor(
new HelloServiceImpl());
TServer server = new TNonblockingServer(processor, serverTransport);
System.out.println("Start server on port 10005 ...");
server.serve();
} catch (TTransportException e) {
e.printStackTrace();
}HelloServiceAsyncServer 通过 java.nio.channels.ServerSocketChannel 创建非阻塞的服务器端等待客户端的连接。创建异步客户端实现代码,调用 Hello.AsyncClient 访问服务端的逻辑实现,将 MethodCallback 对象作为参数传入调用方法中,代码如下:清单 14.HelloServiceAsyncClient.java package service.
import java.io.IOE
import org.apache.thrift.async.AsyncMethodC
import org.apache.thrift.async.TAsyncClientM
import org.apache.thrift.protocol.TBinaryP
import org.apache.thrift.protocol.TProtocolF
import org.apache.thrift.transport.TNonblockingS
import org.apache.thrift.transport.TNonblockingT
import service.callback.MethodC
import service.demo.H
public class HelloServiceAsyncClient {
* 调用 Hello 服务
* @param args
public static void main(String[] args) throws Exception {
TAsyncClientManager clientManager = new TAsyncClientManager();
TNonblockingTransport transport = new TNonblockingSocket(
"localhost", 10005);
TProtocolFactory protocol = new TBinaryProtocol.Factory();
Hello.AsyncClient asyncClient = new Hello.AsyncClient(protocol,
clientManager, transport);
System.out.println("Client calls .....");
MethodCallback callBack = new MethodCallback();
asyncClient.helloString("Hello World", callBack);
Object res = callBack.getResult();
while (res == null) {
res = callBack.getResult();
System.out.println(((Hello.AsyncClient.helloString_call) res)
.getResult());
} catch (IOException e) {
e.printStackTrace();
}HelloServiceAsyncClient 通过 java.nio.channels.Socketchannel 创建异步客户端与服务器建立连接。在本文中异步客户端通过以下的循环代码实现了同步效果,读者可去除这部分代码后再运行对比。清单 15. 异步客户端实现同步效果代码段Object res = callBack.getResult();
// 等待服务调用后的返回结果
while (res == null) {
res = callBack.getResult();
}通过与清单 9 和清单 10 的代码比较,我们可以构建一个 TNonblockingServer 服务类型的服务端,在客户端构建一个 TFramedTransport 传输层的同步客户端和一个 TNonblockingTransport 传输层的异步客户端,那么一个服务就可以通过一个 socket 端口提供两种不同的调用方式。有兴趣的读者可以尝试一下。常见问题NULL 问题我们在对服务的某个方法调用时,有时会出现该方法返回 null 值的情况,在 Thrift 中,直接调用一个返回 null 值的方法会抛出 TApplicationException 异常。在清单 2 中,HelloServiceImpl 里实现了 helloNull 方法,返回 null 值,我们在 HelloServiceClient.java 中加入调用该方法的代码,出现如下图所示的异常:图 4. TApplicationException 异常为了处理返回 null 值情况,我们要捕获该异常,并进行相应的处理,具体客户端代码实现如下:清单 16. 处理服务返回值为 null 的代码 package service.
import org.apache.thrift.TApplicationE
import org.apache.thrift.TE
import org.apache.thrift.protocol.TBinaryP
import org.apache.thrift.protocol.TP
import org.apache.thrift.transport.TS
import org.apache.thrift.transport.TT
import org.apache.thrift.transport.TTransportE
import service.demo.H
public class HelloServiceClient {
* 调用 Hello 服务,并处理 null 值问题
* @param args
public static void main(String[] args) {
TTransport transport = new TSocket("localhost", 7911);
transport.open();
TProtocol protocol = new TBinaryProtocol(transport);
Hello.Client client = new Hello.Client(protocol);
System.out.println(client.helloNull());
transport.close();
} catch (TTransportException e) {
e.printStackTrace();
} catch (TException e) {
if (e instanceof TApplicationException
&& ((TApplicationException) e).getType() ==
TApplicationException.MISSING_RESULT) {
System.out.println("The result of helloNull function is NULL");
}调用 helloNull 方法后,会抛出 TApplicationException 异常,并且异常种类为 MISSING_RESULT,本段代码显示,捕获该异常后,直接在控制台打印“The result of helloNull function is NULL”信息。安装部署Apache Thrift 的官方网站为:,具体安装步骤如下:
下载 thrift 源文件()
将 thrift 源文件导入 eclipse,进入 /lib/java 目录,使用 ant 编译 build.xml 获得 libthrift-0.6.1-snapshot.jar
将 libthrift-0.6.1-snapshot.jar、slf4j-api-1.5.8.jar、slf4j-log4j12-1.5.8.jar 和 log4j-1.2.14.jar 导入 eclipse 开发环境
下载 thrift 编译工具,该工具可将 thrift 脚本文件编译成 java 文件,下载地址:
创建 Hello.thrift 脚本文件,具体代码如上一章节所述,进入 thrift-0.6.1.exe 所在目录,执行命令"thrift-0.6.1.exe -gen java x:\Hello.thrift",在当前运行盘符下,可看见 gen-java 目录,进入目录可看到生成的 Java 代码。更多 thrift 的命令内容,请参考 thrift 自带的 help 命令
编写服务端和客户端代码,完成 thrift 的安装和部署基于 Apache Thrift 框架生成的服务包括客户端和服务器端,具体的部署模式如下所示:图 5. 部署图从图中我们可以看到,客户端和服务器端部署时,需要用到公共的 jar 包和 java 文件,如图“Common file”区域,其中 Hello.java 由 Hello.thrift 编译而来。在服务器端,服务必须实现 Hello.Iface 接口,同时要包括服务器的启动代码 HelloServiceServer.java。在客户端,包括客户端调用服务的代码 HelloServiceClient.java。客户端和服务器通过 Hello.java 提供的 API 实现远程服务调用。总结本文介绍了 Apache Thrift 的安装部署和架构,并通过大量实例介绍了在不同情况下如何使用 Apache Thrift 来构建服务,同时着重介绍了 Thrift 异步客户端的构建,希望能给读者带来一些帮助。
参考资料 :可下载 Thrift 工具和源码。:Thrift 的功能特点和不足之处。:介绍 Thrift 架构、协议、传输层和服务端类型,并与其他构建服务的方法 ( 如:REST) 进行比较分析。:Thrift 的安装部署说明:Thrift 官方文档,详细介绍 Thrift 的设计:关于 Apache Thrift 0.6.1 构建服务端和客户端的 API 手册:Thrift 的简单应用实例:关于 Thrift 异步客户端的介绍:这里有数百篇关于 Java 编程各个方面的文章。
加入 。查看开发人员推动的博客、论坛、组和维基,并与其他 developerWorks 用户交流。
developerWorks: 登录
标有星(*)号的字段是必填字段。
保持登录。
单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件。
在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。
所有提交的信息确保安全。
选择您的昵称
当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。昵称长度在 3 至 31 个字符之间。
您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。
标有星(*)号的字段是必填字段。
(昵称长度在 3 至 31 个字符之间)
单击提交则表示您同意developerWorks 的条款和条件。 .
所有提交的信息确保安全。
文章、教程、演示,帮助您构建、部署和管理云应用。
立即加入来自 IBM 的专业 IT 社交网络。
为灾难恢复构建应用,赢取现金大奖。
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=Java technologyArticleID=787660ArticleTitle=Apache Thrift - 可伸缩的跨语言服务开发框架
publish-date=Thrift下java服务器与客户端开发指南_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
Thrift下java服务器与客户端开发指南
上传于||文档简介
&&用​T​h​r​i​f​t​开​发​j​a​v​a​ ​s​e​r​v​e​r​与​c​l​i​e​n​t​的​简​单​实​例
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
下载文档到电脑,查找使用更方便
还剩5页未读,继续阅读
你可能喜欢thrift入门教程 - 简书
下载简书移动应用
写了28422字,被27人关注,获得了53个喜欢
thrift入门教程
Thrift最初由Facebook研发,主要用于各个服务之间的RPC通信,支持跨语言,常用的语言比如C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml都支持。Thrift是一个典型的CS(客户端/服务端)结构,客户端和服务端可以使用不同的语言开发。既然客户端和服务端能使用不同的语言开发,那么一定就要有一种中间语言来关联客户端和服务端的语言,没错,这种语言就是IDL(Interface Description Language)。
Thrift IDL
本节介绍Thrift的接口定义语言,Thrift IDL支持的数据类型包含:
thrift不支持无符号类型,因为很多编程语言不存在无符号类型,比如java
byte: 有符号字节
i16: 16位有符号整数
i32: 32位有符号整数
i64: 64位有符号整数
double: 64位浮点数
string: 字符串
集合中的元素可以是除了service之外的任何类型,包括exception。
list&T&: 一系列由T类型的数据组成的有序列表,元素可以重复
一系列由T类型的数据组成的无序集合,元素不可重复
map&K, V&: 一个字典结构,key为K类型,value为V类型,相当于Java中的HMap&K,V&
结构体(struct)
就像C语言一样,thrift也支持struct类型,目的就是将一些数据聚合在一起,方便传输管理。struct的定
义形式如下:
struct People {
枚举(enum)
枚举的定义形式和Java的Enum定义差不多,例如:
enum Sex {
异常(exception)
thrift支持自定义exception,规则和struct一样,如下:
exception RequestException {
服务(service)
thrift定义服务相当于Java中创建Interface一样,创建的service经过代码生成命令之后就会生成客户端和服务端的框架代码。定义形式如下:
service HelloWordService {
// service中定义的函数,相当于Java interface中定义的函数
string doAction(1: string name, 2: i32 age);
thrift支持类似C++一样的typedef定义,比如:
typedef i32 Integer
typedef i64 Long
注意,末尾没有逗号或者分号
常量(const)
thrift也支持常量定义,使用const关键字,例如:
const i32 MAX_RETRIES_TIME = 10
const string MY_WEBSITE = "http://qifuguang.me";
末尾的分号是可选的,可有可无,并且支持16进制赋值
thrift的命名空间相当于Java中的package的意思,主要目的是组织代码。thrift使用关键字namespace定义命名空间,例如:
namespace java com.winwill.thrift
格式是:namespace 语言名 路径, 注意末尾不能有分号。
thrift也支持文件包含,相当于C/C++中的include,Java中的import。使用关键字include定义,例 如:
include "global.thrift"
thrift注释方式支持shell风格的注释,支持C/C++风格的注释,即#和//开头的语句都单当做注释,/**/包裹的语句也是注释。
可选与必选
thrift提供两个关键字required,optional,分别用于表示对应的字段时必填的还是可选的。例如:
struct People {
2: optional i32
表示name是必填的,age是可选的。
知道了怎么定义thirtf文件之后,我们需要用定义好的thrift文件生成我们需要的目标语言的源码,本文以生成java源码为例。假设现在定义了如下一个thrift文件:
namespace java com.winwill.thrift
enum RequestType {
SAY_HELLO,
QUERY_TIME,
//询问时间
struct Request {
1: required RequestT
// 请求的类型,必选
// 发起请求的人的名字,必选
3: optional i32
// 发起请求的人的年龄,可选
exception RequestException {
1: required i32
service HelloWordService {
string doAction(1: Request request) throws (1:RequestException qe); // 可能抛出异常。
在终端运行如下命令(前提是已经安装thrift):
thrift --gen java Test.thrift
则在当前目录会生成一个gen-java目录,该目录下会按照namespace定义的路径名一次一层层生成文件夹,到gen-java/com/winwill/thrift/目录下可以看到生成的4个Java类:
可以看到,thrift文件中定义的enum,struct,exception,service都相应地生成了一个Java类,这就是能支持Java语言的基本的框架代码。
服务端实现
上面代码生成这一步已经将接口代码生成了,现在需要做的是实现HelloWordService的具体逻辑,实现的方式就是创建一个Java类,implements com.winwill.thrift.HelloWordService,例如:
package com.winwill.
import mons.lang3.StringU
import org.apache.thrift.TE
import java.util.D
* @author qifuguang
* @date 15/9/11 15:53
public class HelloWordServiceImpl implements com.winwill.thrift.HelloWordService.Iface {
// 实现这个方法完成具体的逻辑。
public String doAction(com.winwill.thrift.Request request) throws com.winwill.thrift.RequestException, TException {
System.out.println("Get request: " + request);
if (StringUtils.isBlank(request.getName()) || request.getType() == null) {
throw new com.winwill.thrift.RequestException();
String result = "Hello, " + request.getName();
if (request.getType() == com.winwill.thrift.RequestType.SAY_HELLO) {
result += ", Welcome!";
result += ", Now is " + new Date().toLocaleString();
上面这个就是服务端的具体实现类,现在需要启动这个服务,所以需要一个启动类,启动类的代码如下:
package com.winwill.
import org.apache.thrift.server.TS
import org.apache.thrift.server.TSimpleS
import org.apache.thrift.transport.TServerS
import java.net.ServerS
* @author qifuguang
* @date 15/9/11 16:07
public class HelloWordServer {
public static void main(String[] args) throws Exception {
ServerSocket socket = new ServerSocket(7912);
TServerSocket serverTransport = new TServerSocket(socket);
com.winwill.thrift.HelloWordService.Processor processor = new com.winwill.thrift.HelloWordService.Processor(new HelloWordServiceImpl());
TServer server = new TSimpleServer(processor, serverTransport);
System.out.println("Running server...");
server.serve();
运行之后看到控制台的输出为:
Running server...
客户端请求
现在服务已经启动,可以通过客户端向服务端发送请求了,客户端的代码如下:
package com.winwill.
import org.apache.thrift.protocol.TBinaryP
import org.apache.thrift.protocol.TP
import org.apache.thrift.transport.TS
import org.apache.thrift.transport.TT
* @author qifuguang
* @date 15/9/11 16:13
public class HelloWordClient {
public static void main(String[] args) throws Exception {
TTransport transport = new TSocket("localhost", 8888);
TProtocol protocol = new TBinaryProtocol(transport);
// 创建client
com.winwill.thrift.HelloWordService.Client client = new com.winwill.thrift.HelloWordService.Client(protocol);
transport.open();
// 建立连接
// 第一种请求类型
com.winwill.thrift.Request request = new com.winwill.thrift.Request()
.setType(com.winwill.thrift.RequestType.SAY_HELLO).setName("winwill2012").setAge(24);
System.out.println(client.doAction(request));
// 第二种请求类型
request.setType(com.winwill.thrift.RequestType.QUERY_TIME).setName("winwill2012");
System.out.println(client.doAction(request));
transport.close();
// 请求结束,断开连接
运行客户端代码,得到结果:
Hello, winwill2012, Welcome!Hello, winwill2012, Now is
并且此时,服务端会有请求日志:
Running server...Get request: Request(type:SAY_HELLO, name:winwill2012, age:24)Get request: Request(type:QUERY_TIME, name:winwill2012, age:24)
可以看到,客户端成功将请求发到了服务端,服务端成功地将请求结果返回给客户端,整个通信过程完成。
本文为作者个人理解,如理解有误,请留言相告,感激不尽;
本文为作者原创,转载请注明出处,原文地址:
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
被以下专题收入,发现更多相似内容:
关注互联网、科技。
**诚邀科技爱好者一起管理这个专题,私信我。
不定期会精选一些好的文章发在公众号(joojencom)...
· 27049人关注
互联网编程、web、it
· 2988人关注
· 221人关注
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
选择支付方式:}

我要回帖

更多关于 thrift生成java代码 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信