一.什么是thrift
thrift是Facebook开源出来的项目,现在交给了Apache来管理。thrift是用来针对不同语言系统之间数据调用的。thrift支持c,c++,Erlang,java,python,ruby,php等语言。thrift允许定义一个简单的定义文件中的数据类型和服务接口,这个文件就是IDL(Interface Definition Language),以作为输入文件,编译器生成代码。简单的说就是thrift定义了统一的文件(对象或者结构体,服务接口),使用thrift的编译器能够生成对应语言的代码文件。thrft之所以是跨语言的原意就是他通过语言无关的自定义语言来生成语言相关的代码。
二.thrift数据类型
thrift的数据类型,包括基本类型,结构体类型,容器类型,异常类型,定义服务
1.基本类型
- bool 布尔类型 值为 true 或者 false 对应java中的boolean
- byte 8位有符号整数 对应java中的byte
- i16 16位有符号整数 对应java中的 short
- i32 32位有符号整数 对应java中int
- i64 64位有符号整数 对应java中的long
- double 浮点型 对应java中的double
- string 字符串类型 对应java中的String类型 utf-8编码
2.结构体类型
这个结构体类型对应C语言中的结构体,java或者C++中的class,结构体应该可以嵌套结构体的。使用struct定义
3.容器类型
- list 对应java中的ArrayList
- map 对应java中的Hashmap
- set 对应java中的HashSet
4.服务类型
利用关键字service定义的。定义的就是接口。
5.异常类型
使用关键字exception定义的,定义的就是异常对象
6.枚举类型
使用关键字enum定义的。
三.Thrift在java中的使用
- 下载Thrift客户端
从官网上下载相应的Thrift.我使用的windows,所以下载的是windows客户端(thrift-0.9.2.exe)。这个客户端非常小巧,他的作用就是把ids文件生成相对应的语言的代码文件。下载下载之后改名为thrift.exe丢到系统盘中的windows目录下面。这样在cmd下就能直接使用thrift的命令了。 - 编写thrift的IDL文件。
- exp.thrift
namespace java com.lubby.service.info
exception ServiceException{
1: i32 code; //错误编号
2: string msg; //错误码
3: string data; //错误描述信息
}
namespace java com.lubby.service.info
exception ServiceException{
1: i32 code; //错误编号
2: string msg; //错误码
3: string data; //错误描述信息
}
info.thrift 使用struct定义对象类
namespace java com.lubby.service.info
struct Parameters{
1: i32 a; //参数a
2: i32 b; //参数b
3: string message; //其他信息
}
namespace java com.lubby.service.info
struct Parameters{
1: i32 a; //参数a
2: i32 b; //参数b
3: string message; //其他信息
}
service.thrift
include "info.thrift"
include "../common/exp.thrift"
namespace java com.lubby.service
service MathUtil {
/**
* 计算两个整数之和
*/
i32 getIntegerSum(1: info.Parameters paramters) throws(1: exp.ServiceException ex);
/**
* 计算两个浮点数之和
*/
double getDoubleSum(1: double a, 2: double b) throws(1: exp.ServiceException ex);
}
include "info.thrift"
include "../common/exp.thrift"
namespace java com.lubby.service
service MathUtil {
/**
* 计算两个整数之和
*/
i32 getIntegerSum(1: info.Parameters paramters) throws(1: exp.ServiceException ex);
/**
* 计算两个浮点数之和
*/
double getDoubleSum(1: double a, 2: double b) throws(1: exp.ServiceException ex);
}
利用thrift命令生成java源文件
这里就是生成好的代码
编写接口实现
public class MathUtilImpl implements MathUtil.Iface {
public double getDoubleSum(double a, double b) throws ServiceException,
TException {
return a + b;
}
@Override
public int getIntegerSum(Parameters paramters) throws ServiceException,
TException {
System.out.println(paramters.getMessage());
return paramters.getA() + paramters.getB();
}
}
public class MathUtilImpl implements MathUtil.Iface {
public double getDoubleSum(double a, double b) throws ServiceException,
TException {
return a + b;
}
@Override
public int getIntegerSum(Parameters paramters) throws ServiceException,
TException {
System.out.println(paramters.getMessage());
return paramters.getA() + paramters.getB();
}
}
服务端开启服务
/**
* @author lubby:
* @version 创建时间:2015年6月9日 下午6:32:43 类说明
*
* 实现服务处理接口impl
* 创建TProcessor
* 创建TServerTransport
* 创建TProtocol
* 创建TServer
* 启动Server
*/
public class ThriftServer {
private int port = 9001;
private String address = "127.0.0.1";
public static void main(String[] args) {
ThriftServer thriftServer = new ThriftServer();
thriftServer.nonBlockService();
// thriftServer.service();
}
public void nonBlockService(){
TProcessor processor = new MathUtil.Processor<Iface>(new MathUtilImpl());
/** 非阻塞IO */
try {
TNonblockingServerSocket tSocketTranport = new TNonblockingServerSocket(
new InetSocketAddress(address, port));
TNonblockingServer.Args targs = new TNonblockingServer.Args(
tSocketTranport);
targs.processor(processor);
targs.protocolFactory(new TCompactProtocol.Factory());
targs.transportFactory(new TFramedTransport.Factory());
TServer server = new TNonblockingServer(targs);
System.out.println("server begin ......................");
server.serve();
System.out.println("---------------------------------------");
} catch (TTransportException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void service() {
Processor processor = new MathUtil.Processor<Iface>(new MathUtilImpl());
try {
// 定义通信协议 这里服务端使用Socket
TServerTransport serverTransport = new TServerSocket(
new InetSocketAddress(address, port));
Args targs = new Args(serverTransport);
targs.processor(processor);
// 使用二进制来编码应用层的数据
// targs.protocolFactory( new TBinaryProtocol.Factory(true, true));
// 使用json来编码解码
// targs.protocolFactory(new TJSONProtocol.Factory());
// 使用压缩格式
targs.protocolFactory(new TCompactProtocol.Factory());
targs.transportFactory(new TTransportFactory());
// 单线程阻塞io
// TServer server = new TSimpleServer(targs);
// 多线程阻塞io
TServer server = new TThreadPoolServer(targs);
System.out.println("server begin ......................");
server.serve();
System.out.println("---------------------------------------");
// server.stop();
} catch (Exception ex) {
}
}
}
/**
* @author lubby:
* @version 创建时间:2015年6月9日 下午6:32:43 类说明
*
* 实现服务处理接口impl
* 创建TProcessor
* 创建TServerTransport
* 创建TProtocol
* 创建TServer
* 启动Server
*/
public class ThriftServer {
private int port = 9001;
private String address = "127.0.0.1";
public static void main(String[] args) {
ThriftServer thriftServer = new ThriftServer();
thriftServer.nonBlockService();
// thriftServer.service();
}
public void nonBlockService(){
TProcessor processor = new MathUtil.Processor<Iface>(new MathUtilImpl());
/** 非阻塞IO */
try {
TNonblockingServerSocket tSocketTranport = new TNonblockingServerSocket(
new InetSocketAddress(address, port));
TNonblockingServer.Args targs = new TNonblockingServer.Args(
tSocketTranport);
targs.processor(processor);
targs.protocolFactory(new TCompactProtocol.Factory());
targs.transportFactory(new TFramedTransport.Factory());
TServer server = new TNonblockingServer(targs);
System.out.println("server begin ......................");
server.serve();
System.out.println("---------------------------------------");
} catch (TTransportException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void service() {
Processor processor = new MathUtil.Processor<Iface>(new MathUtilImpl());
try {
// 定义通信协议 这里服务端使用Socket
TServerTransport serverTransport = new TServerSocket(
new InetSocketAddress(address, port));
Args targs = new Args(serverTransport);
targs.processor(processor);
// 使用二进制来编码应用层的数据
// targs.protocolFactory( new TBinaryProtocol.Factory(true, true));
// 使用json来编码解码
// targs.protocolFactory(new TJSONProtocol.Factory());
// 使用压缩格式
targs.protocolFactory(new TCompactProtocol.Factory());
targs.transportFactory(new TTransportFactory());
// 单线程阻塞io
// TServer server = new TSimpleServer(targs);
// 多线程阻塞io
TServer server = new TThreadPoolServer(targs);
System.out.println("server begin ......................");
server.serve();
System.out.println("---------------------------------------");
// server.stop();
} catch (Exception ex) {
}
}
}
客户端连接服务端
/**
* @author lubby:
* @version 创建时间:2015年6月9日 下午6:48:29
* 类说明
*
*
* 创建Transport
* 创建TProtocol
* 基于TTransport和TProtocol创建 Client
* 调用Client的相应方法
*
*
*/
public class ThriftClient {
public static void main(String[] args) throws ServiceException, TException{
//定义传输层协议 这里使用Socket
TTransport transport1 = new TSocket("127.0.0.1", 9001);
//
TTransport transport = new TFramedTransport(transport1);
//定义传输层协议 这里使用Http
// TTransport transport = new THttpClient("127.0.0.1");
long start=System.currentTimeMillis();
//定义编码解码协议 这里使用二进制
// TProtocol protocol = new TBinaryProtocol(transport);
//定义编码协议 这里使用json格式
// TProtocol protocol = new TJSONProtocol(transport);
//定义编码解码协议 这里使用压缩格式
TProtocol protocol = new TCompactProtocol(transport);
//当使用服务端使用非阻塞服务时,客户端要设置protocol为frame
MathUtil.Client client = new MathUtil.Client(protocol);
transport.open();
Parameters params = new Parameters();
// params.setA(1);
// params.setB(2);
params.a = 1;
params.b = 2;
params.message = "client request .....";
int result1 = client.getIntegerSum(params);
double result2 = client.getDoubleSum(1.2, 2.4);
transport.close();
System.out.println(result1);
System.out.println(result2);
System.out.println(1.2+2.4);
}
}
/**
* @author lubby:
* @version 创建时间:2015年6月9日 下午6:48:29
* 类说明
*
*
* 创建Transport
* 创建TProtocol
* 基于TTransport和TProtocol创建 Client
* 调用Client的相应方法
*
*
*/
public class ThriftClient {
public static void main(String[] args) throws ServiceException, TException{
//定义传输层协议 这里使用Socket
TTransport transport1 = new TSocket("127.0.0.1", 9001);
//
TTransport transport = new TFramedTransport(transport1);
//定义传输层协议 这里使用Http
// TTransport transport = new THttpClient("127.0.0.1");
long start=System.currentTimeMillis();
//定义编码解码协议 这里使用二进制
// TProtocol protocol = new TBinaryProtocol(transport);
//定义编码协议 这里使用json格式
// TProtocol protocol = new TJSONProtocol(transport);
//定义编码解码协议 这里使用压缩格式
TProtocol protocol = new TCompactProtocol(transport);
//当使用服务端使用非阻塞服务时,客户端要设置protocol为frame
MathUtil.Client client = new MathUtil.Client(protocol);
transport.open();
Parameters params = new Parameters();
// params.setA(1);
// params.setB(2);
params.a = 1;
params.b = 2;
params.message = "client request .....";
int result1 = client.getIntegerSum(params);
double result2 = client.getDoubleSum(1.2, 2.4);
transport.close();
System.out.println(result1);
System.out.println(result2);
System.out.println(1.2+2.4);
}
}
四.关于protocol和transport
回头有时间在写。