Thrift - 01:初识thrift

235 阅读2分钟

前言

本篇主要是针对apache-thrift原生api使用的案例,涉及thrift依赖、IDL示例、编译器安装、插件配置以及客户端调用。apache-thrift的历史背景以及与swift的渊源可自行了解。话不多说,直接上干货。

项目依赖

本文章以及本系列后续文章主要以maven项目为主,thrift相关依赖如下

<dependency>
  <groupId>org.apache.thrift</groupId>
  <artifactId>libthrift</artifactId>
  <version>0.21.0</version>
</dependency>

idl示例

Thrift IDL,即Thrift接口定义语言(Interface Definition Language),是Facebook开发并开源的一种用于跨语言通讯的接口描述语言。它允许开发者定义服务接口、数据类型和异常处理等信息,然后通过Thrift提供的编译器编译成不同语言的代码,从而实现跨语言调用。

这里只简单介绍使用示例,会在后续文章中分享更细节的使用。以下是service的idl文件

namespace java ltd.klein.thrift

service ExampleService {

   string sayHello(1:string name)
}

编译器安装

编译器的作用是将idl文件编译为Java文件。

以mac为例:brew install thrift

windows可下载安装包进行安装

maven插件

<build>
  <directory>target</directory>
  <plugins>
    <!-- thrift插件 -->
    <plugin>
      <groupId>org.apache.thrift.tools</groupId>
      <artifactId>maven-thrift-plugin</artifactId>
      <version>0.1.11</version>
      <executions>
        <execution>
          <id>thrift-sources</id>
          <phase>generate-sources</phase>
          <goals>
            <goal>compile</goal>
          </goals>
          <configuration>
            <thriftExecutable>thrift</thriftExecutable> <!-- Thrift 编译器路径 -->
            <generator>java</generator>  <!-- 生成 Java 代码 -->
            <thriftSourceRoot>${basedir}/src/main/thrift</thriftSourceRoot>
            <outputDirectory>${project.build.directory}/generated-sources/thrift</outputDirectory>
          </configuration>
        </execution>
        <execution>
          <id>thrift-test-sources</id>
          <phase>generate-test-sources</phase>
          <goals>
            <goal>testCompile</goal>
          </goals>
        </execution>
      </executions>
      <configuration>
        <generator>java:beans</generator>
      </configuration>
    </plugin>
    <!-- 添加 build-helper-maven-plugin 插件,将thrift IDL编译后的Java代码添加到编译路径下 -->
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>build-helper-maven-plugin</artifactId>
      <version>3.4.0</version>
      <executions>
        <execution>
          <id>add-source</id>
          <phase>generate-sources</phase>
          <goals>
            <goal>add-source</goal>
          </goals>
          <configuration>
            <sources>
              <source>${project.build.directory}/generated-sources/thrift</source>
            </sources>
          </configuration>
        </execution>
      </executions>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.8.1</version> <!-- 使用适合你项目的版本 -->
      <configuration>
        <source>11</source> <!-- 指定源代码的Java版本 -->
        <target>11</target> <!-- 指定目标代码的Java版本 -->
        <encoding>UTF-8</encoding> <!-- 指定源代码文件的编码 -->
        <compilerArgs>
          <arg>-Xlint:all</arg>
        </compilerArgs>
      </configuration>
      <!-- 可以在这里配置插件的执行目标,但通常编译插件的默认目标已经足够 -->
    </plugin>
  </plugins>
</build>

客户端

package ltd.klein;

import ltd.klein.thrift.ExampleService;
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;

/**
 * @author Klein
 * @date 2024-10-10 15:46
 */
public class ExampleClient {

   // 客户端调用
   public static void main(String[] args) {
      try {
         TTransport transport = new TSocket("localhost", 9091);
         transport.open();

         TProtocol protocol = new TBinaryProtocol(transport);
         ExampleService.Client client = new ExampleService.Client(protocol);

         System.out.println("Server client start: ");
         String response = client.sayHello("World");
         System.out.println("Server response: " + response);

         transport.close();
      } catch (TTransportException e) {
         e.printStackTrace();
      } catch (TException e) {
         e.printStackTrace();
      }
   }
}

服务端

package ltd.klein;

import ltd.klein.thrift.ExampleService;
import org.apache.thrift.TBaseAsyncProcessor;
import org.apache.thrift.TBaseProcessor;
import org.apache.thrift.TException;
import org.apache.thrift.TMultiplexedProcessor;
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;
import org.apache.thrift.transport.TServerTransport;

import javax.annotation.processing.Processor;

/**
 * @author Klein
 * @date 2024-10-10 15:45
 */
public class Server {

   // 服务端启动
   public static void main(String[] args) {
      try {
         TProcessor processor = new ExampleService.Processor<>(new ExampleServiceHandler());
         TServerTransport serverTransport = new TServerSocket(9091);
         TServer server = new TSimpleServer(new TServer.Args(serverTransport).processor(processor).protocolFactory(new TBinaryProtocol.Factory()));

         System.out.println("Starting the server...");
         server.serve();

      } catch (Exception e) {
         e.printStackTrace();
      }

   }

   // 服务端
   public static class ExampleServiceHandler implements ExampleService.Iface {

      @Override
      public String sayHello(String name) throws TException {
         System.out.println("hell " + name);
         return "Hello, " + name;
      }
   }

}

执行结果

Server client start:

Server response: Hello, World

总结

至此,thrift的初步使用就结束了,后续会分享更多的使用案例,如结合SpringBoot使用等。如有问题,欢迎留言讨论,相互提升。