Thrift 首次使用小记

国庆放假闲着没事,乱逛,到了Apache的网站上去看了看,按语言浏览开源项目时,竟然看到有的delphi,颇感意外(虽然搞到最后才知道好像这玩意不支持我现在工作主要用的delphi 7,⊙﹏⊙),就进去看了下,项目名叫Thrift,没见过,新鲜玩意,官方介绍如下:

The Apache Thrift software framework, for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages.

简言之:它是用来开发后台服务的框架,可扩展、跨语言,结合了一个软件栈,实现了代码自动生成,在上面一堆语言之间构建高效无缝的服务。

在网上又google了一些相关信息,了解这个原来是大名鼎鼎的facebook公司开发的用来解决跨语言的服务调用的问题,传统的webservice或者其他的服务调用的返回很多都是xml或者json等格式,数据量太大了,该项目就是用来解决这个问题的,它的数据传输可以是基于二进制流的,所以这点吸引了我,至于具体的优点什么的可以自己google了。

我下面就重点说下Thrift的安装,以及demo,其实主要时间都花在环境搭建上了。

下面就开始说怎么搭建环境,我是在windows xp上做的试验:

1.下载、安装Cygwin(在windows模拟unix的操作环境)

下载地址:http://cygwin.com/setup.exe

安装过程中选下安装的路径,也就是它的根目录,我选的是C:\Program Files\cygwin,后面还有个下载站点的选择,我选了个edu.cn结尾的,速度还行,其余就都按照默认一路下去就可以了 

2.ant

我之前已经装过了,环境变量什么的也配过了,所以不用搞了(cygwin对windows的环境变量也可以直接使用)

3.下载、安装thrift

http://thrift.apache.org/download/

需要下载(现在的版本是0.8.0)

两个都得下在下来,thrift-0.8.0.tar.gz,我把它放到了cygwin的用户目录下C:\Program Files\cygwin\home\Jadic Wei下

按网上好多版本说的直接解压这个文件,我启动了Cygwin Terminal(安装后好桌面有快捷方式),输入解压命令:

$ tar -zxvf thrift-0.8.0.tar.gz

得到如下提示

tar: 它似乎不像是一个 tar 归档文件
tar: 跳转到下一个头
tar: 由于前次错误,将以上次的错误状态退出

后又得网上一网友的提醒,这样就搞定了,先是:

$ gunzip thrift-0.8.0.tar.gz

意思就是先要gz文件解压, 接着:

$ tar -zxvf thrift-0.8.0.tar

就解压好了,

后面按照网友说的就是安装thrift了,

我参照了这个做了下(http://blog.csdn.net/zj_1395201/article/details/6985293)可只有下面这一步成功了

就是thrift的主目录,然后

./configure

下面的就是执行不行,提示我compiler/cpp是个目录,确实是个目录,我不知道是不是我哪边输入的不对,对linux的东西不了解,然后又上网查了查

看到一个网友说的刚才上面下载的thrift-0.8.0.exe,这个玩意为了后面使用方便,改个名,thrift.exe,直接复制到c:\windows目录下,搞到了

这样其实就实现了cygwin中安装thrift的母的,也就是为了后面可以用它来自动生成代码

 

下面就可以用了,同样按照官方的说明我简单些个demo,用的是java写的服务端和客户端

至于如何按照规范写类似于伪代码的文件,大家可以在网上看看它的要求规范,我的例子,文件名d.thrift如下

struct User{
    1:required i32 userId,
    2:string userName,
    3:string userPass,
}

service JNBus {
    bool isUserValid(1: string userName, 2: string userPass),
    i32 login(1: string userName, 2: string userPass),
    User getUser(1: i32 userId),
    list<User> getAllUser(),
}    

自动生成代码:

启动命令行,进入d.thrift所在目录下,执行

thrift -gen java d.thrift

没有错的情况下,会生成一个文件gen-java,里面就是自动生成的代码,生成了两个文件一个User.java,一个JNBus.java,代码太长了,就不贴了

下面就根据自动生成的文件来写服务端和客户端了,但在进入之前得写解决一个问题,就是thrift运行需要的jar包,这是就需要用到ant了,俺是这么做的

通过cygwin进入thrift-0.8.0\lib\java,执行下

ant

会自动将所有需要的jar包下载下来,放在了build文件夹下,将里面的jar包都拷贝出来,以添加到项目中

终于进入最终代码编写了

服务端:

先是服务的实现类:

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 
 4 import org.apache.thrift.TException;
 5 
 6 import com.jadic.thrift.autoGen.*;
 7 
 8 public class JNBusImpl implements JNBus.Iface{
 9 
10     @Override
11     public boolean isUserValid(String userName, String userPass)
12             throws TException {
13         return userName.equals("Jadic") && userPass.equals("Jadic");
14     }
15 
16     @Override
17     public int login(String userName, String userPass) throws TException {
18         return 99;
19     }
20 
21     @Override
22     public User getUser(int userId) throws TException {
23         User user = new User(userId, "Jadic", "Jadic Is Handsome");
24         return user;
25     }
26 
27     @Override
28     public List<User> getAllUser() throws TException {
29         List<User> users = new ArrayList<User>();
30         User user = new User(1, "1", "1");
31         users.add(user);
32         user = new User(2, "2", "2");
33         users.add(user);
34         return users;
35     }
36 
37 }

启动服务的主类:

 1 import org.apache.thrift.server.TServer;
 2 import org.apache.thrift.server.TSimpleServer;
 3 import org.apache.thrift.transport.TServerSocket;
 4 import org.apache.thrift.transport.TServerTransport;
 5 import org.apache.thrift.transport.TTransportException;
 6 
 7 import com.jadic.thrift.autoGen.JNBus;
 8 import com.jadic.thrift.autoGen.JNBus.Iface;
 9 import com.jadic.thrift.autoGen.JNBus.Processor;
10 
11 public class JNBusServer {
12 
13     private JNBusImpl jnBusImpl;
14     private JNBus.Processor<Iface> processor;
15     
16     public JNBusServer() {
17         jnBusImpl = new JNBusImpl();
18         processor = new Processor<JNBus.Iface>(jnBusImpl);
19     }
20     
21     public void startServer() throws TTransportException {
22         TServerTransport serverTransport = new TServerSocket(9090);
23         TServer server = new TSimpleServer(new TServer.Args(serverTransport).processor(processor));
24         System.out.println("Starting the simple server...");
25         server.serve();
26     }
27     
28     public static void main(String[] args) throws TTransportException {
29         JNBusServer jnBusServer = new JNBusServer();
30         jnBusServer.startServer();
31     }
32 }

 

客户端:

 1 import java.util.List;
 2 
 3 import org.apache.thrift.TException;
 4 import org.apache.thrift.protocol.TBinaryProtocol;
 5 import org.apache.thrift.protocol.TProtocol;
 6 import org.apache.thrift.transport.TSocket;
 7 import org.apache.thrift.transport.TTransport;
 8 
 9 import com.jadic.thrift.autoGen.JNBus;
10 import com.jadic.thrift.autoGen.User;
11 import com.jadic.thrift.autoGen.JNBus.Client;
12 
13 public class JNBusClient {
14     
15     public static void main(String[] args) throws TException {
16         TTransport transport = new TSocket("localhost", 9090);
17         transport.open();
18         TProtocol protocol = new TBinaryProtocol(transport);
19         JNBus.Client client = new Client(protocol);
20         log("isUserValid return " + client.isUserValid("Jadic", "Jadic"));
21         log("login return " + client.login("Jadic", "Jadic"));
22         User user = client.getUser(12);
23         log("getUser return " + user.toString());
24         List<User> users = client.getAllUser();
25         log("getAllUser return " + users.size() + " user");
26         for (User u : users) {
27             log(u.toString());
28         }
29     }
30     
31     public static void log(Object msg) {
32         System.out.println(msg);
33     }
34 
35 }

启动服务端,客户端,客户端调用成功,打印如下:

isUserValid return true
login return 99
getUser return User(userId:12, userName:Jadic, userPass:Jadic Is Handsome)
getAllUser return 2 user
User(userId:1, userName:1, userPass:1)
User(userId:2, userName:2, userPass:2)

初步的调用终于成功了

posted on 2012-10-06 00:48  好记性不如烂博客  阅读(2189)  评论(0编辑  收藏  举报