Thrift是facebook开发的一个RPC框架,后来被献给了apache组织,现在是一个开源项目,Thrift不仅是一个RPC框架,同时,它也可以作为一个序列化工具使用。
thrift入门demo需要和protobuf一样,安装thrift可执行环境,windows下可以直接下载可执行文件,想要方便使用,可以修改文件名,去掉版本号为thrift,如下所示:
如果需要在任何命令行下使用,最好将/path/to/thrift文件夹目录加入环境变量path中。这里使用的是最新的版本0.12.0版本。
接着就可以准备thrift文件了,和proto序列化文件类似,这里直接给出HelloWorldService.thrift
namespace java com.xxx.thrift
typedef i16 short
typedef i32 int
typedef i64 long
typedef bool boolean
typedef string String
struct User{
1: required int id,
2: required String name,
3: required int age,
4: optional String mobile
}
service HelloWorldService{
String hello(1: String name);
User getUserById(1: required int id);
int add(1: int a,2: int b);
}
文件说明:
- namespace定义了对应的语言和生成的文件所在的包结构package
- typedef定义了别名,这里为了方便和java中类型一致,我们简单定义了几个类型short,int,long,boolean,String
- struct定义了一个结构体,对应Java中Bean实体类,用于进行序列化
- service定义了接口,需要我们用具体的类去实现
生成Java类:
thrift --gen java com\xxx\thrift\HelloWorldService.thrift
没有报错的话,刷新我们的项目,我们可以看到生成了两个Java类,一个是User.java,一个是HelloWorldService.java,只不过他们所在的目录虽然在src/main/java下,但是自己生成了一个文件夹gen-java,如下所示:
我们这里只需要将HelloWorldService.java和User.java移动到我们的对应目录下,去掉gen-java。如果要在生成java文件的时候不需要gen-java文件夹,可以直接加参数-out,我们可以看thrift --help的提示:
在java maven项目中,需要引入thrift依赖,版本version也是0.12.0:
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.12.0</version>
</dependency>
编写实现类HelloWorldServiceImpl.java,实现HelloWorldService.Iface接口,如下所示:
package com.xxx.thrift;
import java.util.HashMap;
import java.util.Map;
import org.apache.thrift.TException;
public class HelloWorldServiceImpl implements HelloWorldService.Iface{
private Map<Integer, User> cache = new HashMap<Integer, User>();
public void init(){
cache.clear();
User user = new User();
user.setId(1);
user.setName("hello");
user.setAge(18);
user.setMobile("110");
cache.put(1, user);
user = new User();
user.setId(2);
user.setName("thirft");
user.setAge(18);
user.setMobile("119");
cache.put(2, user);
user = new User();
user.setId(3);
user.setName("emergengy");
user.setAge(18);
user.setMobile("120");
cache.put(3, user);
}
@Override
public String hello(String name) throws TException {
return "hello,"+name;
}
@Override
public User getUserById(int id) throws TException {
init();
return cache.get(id);
}
@Override
public int add(int a, int b) throws TException {
return a + b;
}
}
这样,我们的准备工作就做完了,现在,我们需要通过编写server/client来测试我们的rpc框架以及thrift序列化。
编写服务端程序:
package com.xxx.thrift;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
public class HelloWorldServer {
public static final int port = 8090;
public void start(){
System.out.println("thrift server start.");
try {
HelloWorldServiceImpl iface = new HelloWorldServiceImpl();
TProcessor processor = new HelloWorldService.Processor<HelloWorldService.Iface>(iface);
TServerSocket serverSocket = new TServerSocket(port);
TServer.Args args = new TServer.Args(serverSocket);
args.processor(processor);
args.protocolFactory(new TBinaryProtocol.Factory());
TServer server = new TSimpleServer(args);
server.serve();
} catch (Exception e) {
System.out.println("thrift server start error.");
}
}
public static void main(String[] args) {
HelloWorldServer server = new HelloWorldServer();
server.start();
}
}
编写客户端程序 :
package com.xxx.thrift;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
public class HelloWorldClient {
private static final String host = "localhost";
private static final int port = 8090;
private static final int timeout = 2000;
public void start(){
TTransport socket = null;
try {
socket = new TSocket(host, port,timeout);
TProtocol protocol = new TBinaryProtocol(socket);
HelloWorldService.Client client = new HelloWorldService.Client(protocol);
socket.open();
User user = client.getUserById(3);
System.out.println("user(1)->"+user);
System.out.println(client.add(5, 3));
System.out.println(client.hello("thrift"));
} catch (Exception e) {
e.printStackTrace();
}finally{
if(socket!=null){
socket.close();
}
}
}
public static void main(String[] args) {
HelloWorldClient client = new HelloWorldClient();
client.start();
}
}
先后启动服务端、客户端程序,查看运行结果:
客户端打印结果如下:
从客户端打印信息来开,当我们打印User对象实例的时候,直接显示了User(id:3,name:emergency,age:18,mobile:120) ,这说明Thrift框架也是可以做序列化的。