一、语法
Thrift类型系统包括预定义基本类型,用户自定义结构体,容器类型,异常和服务定义。
(1) 基本类型
bool
:布尔类型(
true
or false)
,占一个字节
byte:有符号字节
i16:16位有符号整型
i32:32位有符号整型
i64:64位有符号整型
double
:64位浮点数
string:未知编码或者二进制的字符串
(2) 容器类型
Thrift容器与类型密切相关,它与当前流行编程语言提供的容器类型相对应,采用java泛型风格表示的。Thrift提供了3种容器类型:
List<t1>:一系列t1类型的元素组成的有序表,元素可以重复
Set<t1>:一系列t1类型的元素组成的无序表,元素唯一
Map<t1,t2>:key/value对(key的类型是t1且key唯一,value类型是t2)
(3) 结构体和异常
struct LoginUser{
1:i32 userId,
2:stringloginName,
3:string password,
4:string name
}
exceptionUserNotFound{
1:string message
}
(4) 服务
service UserService{
LoginUsergetUser(1:string loginName)throws(1:UserNotFound unf),
list<LoginUser>getUsers();
}
(5) 枚举类型
enum Operation { ADD = 1, SUBTRACT = 2, MULTIPLY = 3, DIVIDE = 4 }
(6) 常量
Thrift允许用户定义常量,复杂的类型和结构体可使用JSON形式表示。
const
i32 INT_CONST = 1234
const
map<string,string>MAP_CONST = {
"hello": "world", "goodnight": "moon"}
二、Thrift文件
(1) 文件
一个thrift中可以定义多个结构体,并且可以存在引用关系
include
"tweet.thrift"
(2) 命名空间
namespace javacom.test.thrift.loginUser
生成包名为“com.test.thrift.loginUser”的文件目录。
(3) 生成代码
下载thrift-0.9.3.
exe
可以将.thrift文件生成对应的代码
命令:thrift-0.9.3.
exe -r --gen java user.thrift
三、接口实现
(1) 实现被远程调用的方法
public
classUserServiceHandler implementsUserService.Iface{…}
四、服务
(1)发布(阻塞式IO + 多线程处理)服务
/**
* 阻塞式、多线程处理
*
* @param args
*/
@SuppressWarnings({ "unchecked","rawtypes" })
public static voidmain(String[] args) {
try {
//设置传输通道,普通通道
TServerTransportserverTransport = new TServerSocket(7911);
//使用高密度二进制协议
TProtocolFactoryproFactory = new TCompactProtocol.Factory();
//设置处理器HelloImpl
TProcessorprocessor = new Hello.Processor(new HelloImpl());
//创建服务器
TServer server= new TThreadPoolServer(
newArgs(serverTransport)
.protocolFactory(proFactory)
.processor(processor)
);
System.out.println("Startserver on port 7911...");
server.serve();
} catch (Exceptione) {
e.printStackTrace();
}
}
(2) (阻塞式IO + 多线程处理)客户端调用
public static void main(String[] args) throws Exception {
// 设置传输通道 - 普通IO流通道
TTransport transport= new TSocket("localhost", 7911);
transport.open();
//使用高密度二进制协议
TProtocol protocol =new TCompactProtocol(transport);
//创建Client
Hello.Client client= new Hello.Client(protocol);
long start =System.currentTimeMillis();
for(int i=0;i<10000; i++){
client.helloBoolean(false);
client.helloInt(111);
client.helloNull();
client.helloString("dongjian");
client.helloVoid();
}
System.out.println("耗时:" + (System.currentTimeMillis() -start));
//关闭资源
transport.close();
}
(2) 基于非阻塞IO(NIO)的服务端
public static void main(String[] args) {
try {
//传输通道 - 非阻塞方式
TNonblockingServerTransportserverTransport = new TNonblockingServerSocket(7911);
//异步IO,需要使用TFramedTransport,它将分块缓存读取。
TTransportFactorytransportFactory = new TFramedTransport.Factory();
//使用高密度二进制协议
TProtocolFactoryproFactory = new TCompactProtocol.Factory();
//设置处理器 HelloImpl
TProcessorprocessor = new Hello.Processor(new HelloImpl());
//创建服务器
TServer server= new TThreadedSelectorServer(
newArgs(serverTransport)
.protocolFactory(proFactory)
.transportFactory(transportFactory)
.processor(processor)
);
System.out.println("Startserver on port 7911...");
server.serve();
} catch (Exceptione) {
e.printStackTrace();
}
}
(3) 调用非阻塞IO(NIO)服务的客户端
public static void main(String[] args) throws Exception {
//设置传输通道,对于非阻塞服务,需要使用TFramedTransport,它将数据分块发送
TTransporttransport = new TFramedTransport(new TSocket("localhost", 7911));
transport.open();
//使用高密度二进制协议
TProtocol protocol= new TCompactProtocol(transport);
//创建Client
Hello.Client client= new Hello.Client(protocol);
long start =System.currentTimeMillis();
for(int i=0;i<10000; i++){
client.helloBoolean(false);
client.helloInt(111);
client.helloNull();
client.helloString("360buy");
client.helloVoid();
}
System.out.println("耗时:" + (System.currentTimeMillis() -start));
//关闭资源
transport.close();
}
五、 实例
服务端:
package com.thrift.test.thrift;
import org.apache.thrift.TProcessorFactory;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.server.TServer;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TTransportException;
/**
*/
public class Server {
public final static intPORT = 8989;
@SuppressWarnings({"rawtypes", "unchecked" })
private void start() {
try {
TNonblockingServerSocketsocket = new TNonblockingServerSocket(PORT);
finalHello.Processor processor = new Hello.Processor(new HelloImpl());
THsHaServer.Argsarg = new THsHaServer.Args(socket);
// 高效率的、密集的二进制编码格式进行数据传输
// 使用非阻塞方式,按块的大小进行传输,类似于 Java 中的 NIO
arg.protocolFactory(newTCompactProtocol.Factory());
arg.transportFactory(newTFramedTransport.Factory());
arg.processorFactory(newTProcessorFactory(processor));
TServer server= new THsHaServer(arg);
server.serve();
System.out.println("#服务启动-使用:非阻塞&高效二进制编码");
} catch(TTransportException e) {
e.printStackTrace();
} catch (Exceptione) {
e.printStackTrace();
}
}
public static voidmain(String args[]) {
Server srv = newServer();
srv.start();
}
}
客户端
package com.thrift.test.Async;
import java.io.IOException;
import org.apache.thrift.TApplicationException;
import org.apache.thrift.TException;
import org.apache.thrift.async.TAsyncClientManager;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TNonblockingSocket;
import org.apache.thrift.transport.TNonblockingTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
/**
*/
public class Client {
public static finalString address = "127.0.0.1";
public static final intport = 8989;
public static final intclientTimeout = 30000;
public static voidmain_syn() {
TTransport transport= new TFramedTransport(new TSocket(address, port, clientTimeout));
TProtocol protocol =new TCompactProtocol(transport);
Hello.Client client= new Hello.Client(protocol);
try {
transport.open();
System.out.println(client.helloString("larry"));
} catch(TApplicationException e) {
System.out.println(e.getMessage()+ " " + e.getType());
} catch(TTransportException e) {
e.printStackTrace();
} catch (TExceptione) {
e.printStackTrace();
}
transport.close();
}
public static voidmain_asy() throws Exception {
try {
TAsyncClientManagerclientManager = new TAsyncClientManager();
TNonblockingTransporttransport = new TNonblockingSocket(address, port, clientTimeout);
TProtocolFactoryprotocol = new TCompactProtocol.Factory();
Hello.AsyncClientasyncClient = new Hello.AsyncClient(protocol, clientManager, transport);
System.out.println("Clientcalls .....");
MyCallbackcallBack = new MyCallback();
asyncClient.helloString("larry",callBack);
while (true) {
Thread.sleep(1);
}
} catch (IOExceptione) {
e.printStackTrace();
}
}
public static voidmain(String[] args) throws Exception {
main_asy();
}
}
回调函数
package com.thrift.test.Async;
import org.apache.thrift.TException;
import org.apache.thrift.async.AsyncMethodCallback;
import com.thrift.test.Async.Hello.AsyncClient.helloString_call;
/**
*/
public class MyCallback implementsAsyncMethodCallback<helloString_call> {
// 返回结果
@Override
public voidonComplete(helloString_call response) {
System.out.println("onComplete");
try {
System.out.println(response.getResult().toString());
} catch (TExceptione) {
e.printStackTrace();
}
}
// 返回异常
@Override
public voidonError(Exception exception) {
System.out.println("onError");
}
}