1. 程式人生 > 實用技巧 >使用thrift的java client呼叫python server

使用thrift的java client呼叫python server

參考:Thrift 連線 Java 與 Python,附 Java 通用工廠方法

上面這篇文章的例子是使用java client呼叫python server中的helloString方法來列印client傳輸過去的字串

thrift檔案,hello.thrift

service Hello {
    string helloString(1:string word)
}

Server端

生成Python server端程式碼

thrift --gen py hello.thrift

python server端程式碼,其中包括生成的hello資料夾中的程式碼,以及server程式碼

from thrift.protocol import TBinaryProtocol
from thrift.server import TServer
from thrift.transport import TSocket
from thrift.transport import TTransport

from hello import Hello


class HelloHandler:
    def __init__(self):
        pass

    def helloString(self, word):
        ret = "hello Thrift! Received: " + word
        return ret


# handler processer類
handler = HelloHandler()
processor = Hello.Processor(handler)
transport = TSocket.TServerSocket("127.0.0.1", 8989)
# 傳輸方式,使用buffer
tfactory = TTransport.TBufferedTransportFactory()
# 傳輸的資料型別:二進位制
pfactory = TBinaryProtocol.TBinaryProtocolFactory()
# 建立一個thrift 服務~
server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)
print("Starting thrift server in python...")
server.serve()
print("done!")

Client端

生成java client程式碼

thrift --gen java hello.thrift

pom檔案

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>thrift-example</artifactId>
    <version>1.0-SNAPSHOT</version>

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

</project>

java client的程式碼

package com.example.tutorial;

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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ThriftFactory {

    private ThriftFactory() {
    }

    private static final Logger LOG = LoggerFactory.getLogger(ThriftFactory.class);
    private static TProtocol protocol;
    private static TTransport transport;

    /**
     * 獲取二進位制 protocol
     *
     * @return 二進位制 protocol
     */
    public static TProtocol getTProtocol() {
        // 單例獲取 protocol
        if (protocol == null) {
            protocol = new TBinaryProtocol(getTTransport());
        }
        return protocol;
    }

    /**
     * 獲取傳輸物件
     *
     * @return 傳輸物件
     */
    public static TTransport getTTransport() {
        // 單例獲取 transport
        if (transport == null) {
            // 應改成從配置檔案讀取
            String ip = "127.0.0.1";
            Integer port = 8989;
            transport = new TSocket(ip, port);
        }
        return transport;
    }

    /**
     * 獲取客戶端例項
     *
     * @param clazz 客戶端類
     * @param <T>   泛型
     * @return 客戶端例項
     */
    public static <T> T getClient(Class<T> clazz) {
        T instance = null;
        try {
            //獲取有參構造器
            Constructor c = clazz.getConstructor(TProtocol.class);
            // 例項化客戶端,需要傳入 protocol
            instance = (T) c.newInstance(getTProtocol());
        } catch (Exception e) {
            LOG.error("", e);
            throw new RuntimeException(e.getMessage());
        }
        return instance;
    }

    /**
     * 發起請求
     *
     * @param clazz      客戶端類
     * @param methodName 方法名,客戶端中不能有過載的方法
     * @param param      方法引數
     * @param <T>        泛型
     * @return 方法返回值
     */
    public static <T> Object doRequest(Class<T> clazz, String methodName, Object... param) {
        Object result = null;
        try {
            // 獲取客戶端例項
            T instance = getClient(clazz);
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                // 獲取指定的方法
                if (method.getName().equals(methodName)) {
                    open();
                    result = method.invoke(instance, param);
                    close();
                    break;
                }
            }
        } catch (Exception e) {
            LOG.error("", e);
            throw new RuntimeException(e.getMessage());
        }
        return result;
    }

    /**
     * 開啟傳輸
     */
    public static void open() {
        try {
            getTTransport().open();
        } catch (TTransportException e) {
            LOG.error("", e);
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 關閉傳輸
     */
    public static void close() {
        getTTransport().close();
    }

}

client主函式

package com.example.tutorial;

public class ThriftExample {

    public static void main(String[] args) {
        String msg = (String) ThriftFactory.doRequest(com.example.tutorial.Hello.Client.class, "helloString", "測試");
        System.out.println(msg);
    }

}

執行python server

執行java client,呼叫了python的helloString方法