一、内容概要
Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目。Thrift通过一个中间语言(IDL, 接口定义语言)来定义RPC的接口和数据类型,然后通过一个编译器生成不同语言的代码(目前支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk和OCaml),并由生成的代码负责RPC协议层和传输层的实现。
上一篇文章着重讲解关于thrift框架的介绍。本文主要讲述的对象是thrift文件,及其client和server的编写方法。
二、Thrift语法
1. Thrift类型
Thrift类型系统包括预定义基本类型,用户自定义结构体,容器类型,异常和服务定义
(1) 基本类型
<span style="font-size:14px;">bool:布尔类型(true or value),占一个字节 byte:有符号字节 i16:16位有符号整型 i32:32位有符号整型 i64:64位有符号整型 double:64位浮点数 string:未知编码或者二进制的字符串</span>
2. 枚举类型
<span style="font-size:14px;">enum NewsType { TOPNEWS, //a SPORTS = 2, //b TECNOLOGY = 3, NBA = 0xa, //c EDU = 5 } //d struct News { 1: i32 id; 2: string title; 3: string content; 4: string source; 5: string author; 6: double score; 7: i64 readNum; 8: NewsType newsType = NewsType.SPORTS; //e } </span>
2.3. 注释
Thrfit支持shell注释风格,C/C++语言中单行或者多行注释风格
# This is a valid comment. /* * This is a multi-line comment. * Just like in C. */ // C++/Java style single-line comments work just as well.
<span style="font-size:14px;">namespace cpp com.example.project // a namespace java com.example.project // b namespace py com.example.project //python namespace php com.example.project //php</span>
namespace java com.example.thrift.service include "NewsModel.thrift" //a service DataSource { string helloWorld(1: string name), bool indexNews(1: NewsModel.News indexNews), //b NewsModel.News getNewsById(1: i32 newsId), map<string,NewsModel.News> getNewsMap(1: i32 newsType), list<NewsModel.News> getNewsList(1: i32 newsType), }
2.6. 定义结构体
结构体由一系列域组成,每个域有唯一整数标识符,类型,名字和可选的缺省参数组成。如:
struct News { 1: required i32 id; //a 2: required string title; //b 3: string content; 4: string source; 5: string author; 6: double score = 4.2; //d 7: i64 readNum; 8: NewsType newsType = NewsType.SPORTS; 10: optional User user; //c } struct User { //e 1: required i32 id; 2: required string userName; 3: required string password; 4: optional string nickName; }
namespace java com.example.thrift.service include "NewsModel.thrift" //“DataSource”与“{”之间需要有空格!!! service DataSource { string helloWorld(1: string name), //a bool indexNews(1: NewsModel.News indexNews), //b NewsModel.News getNewsById(1: i32 newsId), //c map<string,NewsModel.News> getNewsMap(1: i32 newsType), list<NewsModel.News> getNewsList(1: i32 newsType), // ”oneway”标识符表示client发出请求后不必等待回复(非阻塞)直接进行下面的操作, // ”oneway”方法的返回值必须是void oneway void zip() // d }
三、 编译&产生代码
WINDOWS配置thrift开发环境
1.安装thrift:到thrift官网下载exe文件,下载地址:http://thrift.apache.org/download。然后将文件重命名为thrift.exe,拷贝到F:\thrift目录下(或者任何目录下),然后就可以在dos环境下使用了,如下:
F:\thrift>thrift -gen java D:\mywork\javaProject\thriftTest\test.thrift ,输出的java文件默认输出到当前目录下F:\thrift,也可以使用-o参数指定输出路径。
在Windows环境下进行编译时出现以下问题,如图:
原来是编码问题,最后统一thrift文件的编码为UTF-8就可以正常编译通过了。
四、编写Client与Service端
1.下载相关依赖包
a. libthrift.jar
b. slf4j-api.jar
c. slf4j-simple.jar
2.编写接口实现代码
package com.example.thrift.impl; import java.util.List; import java.util.Map; import org.apache.thrift.TException; import com.example.thrift.model.News; import com.example.thrift.service.DataSource; public class DataSourceHandler implements DataSource.Iface{ @Override public String helloWorld(String name) throws TException { // TODO Auto-generated method stub return "hello "+name+",welcom to thrift!"; } @Override public boolean indexNews(News indexNews) throws TException { // TODO Auto-generated method stub return false; } @Override public News getNewsById(int newsId) throws TException { News news = new News(); news.setId(1000); news.setAuthor("Ricky Feng"); news.setContent("thrift demo"); return news; } @Override public Map<String, News> getNewsMap(int newsType) throws TException { // TODO Auto-generated method stub return null; } @Override public List<News> getNewsList(int newsType) throws TException { // TODO Auto-generated method stub return null; } }
package com.example.thrift; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.server.TServer; import org.apache.thrift.server.TSimpleServer; import org.apache.thrift.transport.TServerSocket; import org.apache.thrift.transport.TTransportException; import com.example.thrift.impl.DataSourceHandler; import com.example.thrift.service.DataSource; public class HelloServer { public static final int SERVER_PORT = 8090; public static void main(String[] args) { startServer(); } private static void startServer() { try { System.out.println("HelloServer TSimpleServer start ...."); TProcessor tprocessor = new DataSource.Processor<DataSource.Iface>(new DataSourceHandler()); // 简单的单线程服务模型,一般用于测试 TServerSocket serverTransport = new TServerSocket(SERVER_PORT); TServer.Args tArgs = new TServer.Args(serverTransport); tArgs.processor(tprocessor); tArgs.protocolFactory(new TBinaryProtocol.Factory()); TServer server = new TSimpleServer(tArgs); server.serve(); } catch (TTransportException e) { e.printStackTrace(); } } }
package com.example.thrift; 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.TTransport; import org.apache.thrift.transport.TTransportException; import com.example.thrift.service.DataSource; public class HelloClient { public static final String SERVER_IP = "localhost"; public static final int SERVER_PORT = 8090; public static final int TIMEOUT = 30000; public static void main(String[] args) { startClient(); } private static void startClient() { TTransport transport = null; try { System.out.println("HelloClient start ...."); transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT); // 协议要和服务端一致 TProtocol protocol = new TBinaryProtocol(transport); // TProtocol protocol = new TCompactProtocol(transport); // TProtocol protocol = new TJSONProtocol(transport); DataSource.Client client = new DataSource.Client(protocol); transport.open(); String result = client.helloWorld("Ricky"); System.out.println("Thrify client result =: " + result); } catch (TTransportException e) { e.printStackTrace(); } catch (TException e) { e.printStackTrace(); } finally { if (null != transport) { transport.close(); } } } }
先运行HelloServer启动服务,然后运行HelloClient就可以看见控制台打印:
HelloClient start ....
Thrify client result =: hello Ricky,welcom to thrift!
关于Thrift使用的详细示例可以参考Apache Thrift网站上的Tutorial,地址:http://thrift.apache.org/tutorial/java
最后附上示例代码下载地址:http://download.csdn.net/detail/fx_sky/7499361