概述
Thrift最初由Facebook研发,主要用于各个服务之间的RPC通信。
Thrift是一个典型的CS(客户端/服务端)结构,客户端和服务端可以使用不同的语言开发。
那么它是如何实现使用不同的语言开发呢?答案:用一种中间语言来关联客户端和服务端的语言。
这种语言就是IDL(Interface Description Language)。将这个IDL作为输入文件,编译器就可以生成代码(支持多种),即RPC客户端和服务器通信的无缝跨编程语言。
安装
下载官方链接:http://thrift.apache.org/download
将下载好的thrift-0.10.0 .exe文件命名为thrift .exe,放在D盘下的一个Thtift文件夹中,
为了更方便使用命令,将目录加入到系统Path路径下:
在cmd中输入:thrift -version ,查看是否安装配置成功
出现版本号,安装成功。
定义thrift——IDL文件
IDL文件有许多数据类型
- 结构体类型: struct:定义公共的对象,类似于 C 语 言中的结构体定义,在 Java 中是一个 JavaBean
- 容器类型:
list:对应 Java 的 ArrayList
set:对应 Java 的 HashSet
map:对应 Java 的 HashMap - 异常类型: exception:对应 Java 的 Exception
- 服务类型: service:对应服务的类
这里仅仅定义一个服务。
thrift定义服务相当于Java中创建Interface,创建的service通过代码生成命令生成客户端和服务端的框架代码。
定义形式如下(helloworld.thrift,注意后缀!):
namespace java com.test
service HelloWorldService{
string sayHello(1:string name)
}
——namespace 相当于Java中的package。
在 cmd中 输入命令: thrift -gen java helloworld.thrift
可以看到生成了一个名为gen-java的文件夹,其中就是生成的代码,打开后可以看到层级目录下有:
代码片段:
/**
* Autogenerated by Thrift Compiler (0.10.0)
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
package com.test;
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)", date = "2017-07-18")
public class HelloWorldService {
public interface Iface {
public java.lang.String sayHello(java.lang.String name) throws org.apache.thrift.TException;
}
创建项目
创建一个Maven工程,引入依赖,可在Maven依赖中看到引入的相关Jar包
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.10.0</version>
</dependency>
服务端实现与启动
服务端相关操作的步骤如下:
- 实现服务处理接口Impl
- 创建TProcessor
- 创建TServerTransport
- 创建TProtocol
- 创建TServer
- 启动Server
服务端实现
package com.test;
import org.apache.thrift.TException;
public class HelloWorldImpl implements HelloWorldService.Iface{
public HelloWorldImpl(){
}
public String sayHello(String name) throws TException {
return "Hi," +name + " welcome !";
}
}
服务端启动
package com.test;
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 HelloServer {
public static final int SERVER_PORT = 8090;
public void startServer(){
System.out.println("Server is Runing......");
TProcessor tprocessor = new HelloWorldService.Processor(new HelloWorldImpl());
//简单的单线程服务模型,一般用于测试
try {
TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
TServer.Args tArgs = new TServer.Args(serverTransport);
tArgs.processor(tprocessor);
tArgs.protocolFactory(new TBinaryProtocol.Factory());
TServer server = new TSimpleServer(tArgs);
server.serve();
} catch (Exception e) {
System.out.println("Server start error!");
e.printStackTrace();
}
}
public static void main(String[] args) {
HelloServer server = new HelloServer();
server.startServer();
}
}
运行上面的启动类,控制台输出:Server is Runing……
客户端启动
客户端步骤:
- 创建Transport
- 创建TProtocol
- 基于TTransport和TProtocol创建 Client
- 调用Client的相应方法
客户端启动
package com.test;
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 HelloClient {
public static final String SERVER_IP = "localhost";
public static final int SERVER_PORT = 8090;
public static final int TIMEOUT = 30000;
public void startClient(String userName){
TTransport transport = null;
try {
transport = new TSocket(SERVER_IP,SERVER_PORT,TIMEOUT);
//协议要和服务端一致
TProtocol protocol = new TBinaryProtocol(transport);
HelloWorldService.Client client = new HelloWorldService.Client(protocol);
transport.open();
String result = client.sayHello(userName);
System.out.println("Thrift client result is:"+result);
} catch (Exception e) {
System.out.println("client is error!");
}finally{
if(null != transport){
transport.close();
}
}
}
public static void main(String[] args) {
HelloClient client = new HelloClient();
client.startClient("Z Yong");
}
}
控制台输出
客户端成功收到了服务端返回的请求结果,通信完成。