本文旨在全面的介绍thrift的使用流程,
使用的例子为一个简单的加法服务程序,从客户端发送请求及操作数,服务器端返回加法结果
一、安装篇:
windows:
1. 直接下载windows版本的thrift编译器,http://archive.apache.org/dist/thrift/0.9.0/thrift-0.9.0.exe
下载完成后,将其改名为thrift,并将安装路径添加到系统环境变量PATH中。
2. 下载相应的源码,生成jar包 (详细过程:http://f.dataguru.cn/thread-68637-1-1.html)
注意:thrift编译器的版本必须与相应的jar包版本相同。在windows下生成jar包比较麻烦,此处提供0.9.0版本的jar包供大家使用,上步中下载的编译器也为0.9.0版本
url:
3. 下载org.apache.http及org.apache.commons.logging
http://commons.apache.org/proper/commons-logging/download_logging.cgi
http://hc.apache.org/downloads.cgi
4. 下载slf4j jar包
http://www.slf4j.org/download.html
最后将相应的jar包都添加入eclipse工程的external jars, 就完成了我们的配置工作。
二、.thrift 文件篇:
该文件用于定义所需的数据结构及服务接口。(常用介绍,更详细的范例可以参考https://git-wip-us.apache.org/repos/asf/thrift/?p=thrift.git;a=blob;f=tutorial/tutorial.thrift;h=3150151deceb87e22123c9a321d9cd000dcfce5b;hb=HEAD )
1. 基本数据结构:
bool Boolean, one byte
byte Signed byte
i16 Signed 16-bit integer
i32 Signed 32-bit integer
i64 Signed 64-bit integer
double 64-bit floating point value
string String
binary Blob (byte array)
map<t1,t2> Map from one type to another
list<t1> Ordered list of one type
set<t1> Set of unique elements of one type
更改基本数据结构类型名: typedef i32 MyInteger
定义常量: const i32 INT32CONSTANT = 9853
定义结构体:
struct Work {
1: i32 num1 = 0,
2: i32 num2,
3: Operation op,
4: optional string comment,// optional选项表示如果该变量的值没有被set,它就不会出现在串行化输出中
}
2. 定义服务:
service Calculator extends shared.SharedService {
/**
* A method definition looks like C code. It has a return type, arguments,
* and optionally a list of exceptions that it may throw. Note that argument
* lists and exception lists are specified using the exact same syntax as
* field lists in struct or exception definitions.
*/
void ping(),
i32 add(1:i32 num1, 2:i32 num2),
i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),
/**
* This method has a oneway modifier. That means the client only makes
* a request and does not listen for any response at all. Oneway methods
* must be void.
*/
oneway void zip()
}
我们的thrift文件:
namespace java com.baidu.thrift // 定义输出的语言类型及所属package
service Calculator{ // 定义服务
i32 add(1:i32 num1,2:i32 num2)
}
三、服务处理函数篇 我们的服务处理函数
package com.baidu.thrift;
import com.baidu.thrift.Calculator.Iface; // 格式为 package.服务名.Iface
import org.apache.thrift.TException;
public class CalculatorHandler implements Iface{
@Override
public int add(int num1,int num2) throws TException{ //重载我们在服务中定义的函数add
return num1+num2;
}
}
四、服务器篇
package com.baidu.thrift;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TBinaryProtocol.Factory;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.server.TThreadPoolServer.Args;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TTransportException;
// import the processor of service
import com.baidu.thrift.Calculator;
public class JavaServer {
public final static int PORT = 10005;
public void startServer(){
try {
// 定义socket
TNonblockingServerSocket socket = new TNonblockingServerSocket(PORT);
// 定义服务的处理器,语句格式比较固定
final Calculator.Processor processor = new Calculator.Processor(new CalculatorHandler());
// 定义协议
Factory portFactory = new TBinaryProtocol.Factory(true,true);
// 填充参数
Args args = new Args(socket);
args.processor(processor);
args.protocolFactory(portFactory);
// 创建server
TServer server = new TThreadPoolServer(args);
server.serve();
}catch(TTransportException e){
e.printStackTrace();
}
}
public static void main(String[] args){
System.out.println("Server inits ...");
JavaServer server = new JavaServer();
System.out.println("Server starts ...");
server.startServer();
System.out.println("Completed");
}
}
五、客户端篇
package com.baidu.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;
public class JavaClient {
public void startClient() {
TTransport transport;
try {
System.out.println("thrift client starts ");
transport = new TSocket("localhost", JavaServer.PORT);
TProtocol protocol = new TBinaryProtocol(transport);
Calculator.Client client = new Calculator.Client(protocol);
transport.open();
System.out.println(client.add(10, 20));
transport.close();
System.out.println("Client closes");
} catch (TTransportException e) {
e.printStackTrace();
} catch (TException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println("thrift client inits ");
JavaClient client = new JavaClient();
System.out.println("thrift client starts ");
client.startClient();
System.out.println("thrift client ends ");
}
}
注意: 定义的协议与端口需要与server端一致。最后通过client.服务 调用我们所要使用的服务
原理: 在http://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/ 上有较好的说明,不赘述。