国庆放假闲着没事,乱逛,到了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)
初步的调用终于成功了