基於Thrift的java和PHP互相調用範例

首先咱們看看 Thrift是什麼?php

thrift是一個軟件框架,用來進行可擴展且跨語言的服務的開發。它結合了功能強大的軟件堆棧和代碼生成引擎,以構建在 C++, Java, Go,Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 這些編程語言間無縫結合的、高效的服務。java

是否是感受很酷??那咱們看看怎麼玩的,網上關於 thrift 的範例很多,可是不少都千篇一概,不少都有點殘缺, 下面咱們就展現一下用java來作服務端, 而後客戶端用java和php同時來寫的例子。linux

運行環境:git

win7  x64github

JDK  1.8.Xapache

PHP 5.6編程

其中java部分是在在 Itellj idea裏面基於MAVEN構建的項目。api

廢話很少說,上碼架構

1,首先在idea簡歷maven項目, pom.xml 添加以下類庫框架

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.9.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.2</version>
        </dependency>
    </dependencies>

 

2, 創建 demoHello.thrift 文件內容爲

namespace java com.kedacom.demo.thriftDemo
service  HelloWorldService {
    string sayHello(1:string username)
}

 這種文件是 thrift專用的 IDL文件(Interface Description Language (IDL)), 而後再用 thrift 來生成 java的通用服務代碼,命令以下:

     thrift-0.9.3.exe -r -gen java demoHello.thrift

 thrift的WIN7可執行文件下載  http://archive.apache.org/dist/thrift/0.9.3/thrift-0.9.3.exe, 下載完設置下 系統path就能夠了, 執行命令會在 同目錄下生成 gen-java 文件夾,  裏面的 com\kedacom\demo\thriftDemo 下的HelloWorldService.java 文件就是咱們要用到的,這個文件是定義了咱們的IDL接口引用邏輯的,是把這個RPC接口抽象出來,客戶端能夠鏈接調用

 

3, 而後在項目的  src/main/java 目錄下創建新的package, 命名爲  com.kedacom.demo.thriftDemo,把上面的 HelloWorldService.java 拷貝到packge的目錄下面,  而後在此package新建類HelloClientDemo, HelloServerDemo, HelloWorldImpl,內容分別爲

 

HelloClientDemo

package com.kedacom.demo.thriftDemo;
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;

public class HelloClientDemo {
    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);
            // TProtocol protocol = new TCompactProtocol(transport);
            // TProtocol protocol = new TJSONProtocol(transport);
            HelloWorldService.Client client = new HelloWorldService.Client(protocol);
            transport.open();
            String result = client.sayHello(userName);
            System.out.println("Thrify client result =: " + result);
        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            if (null != transport) {
                transport.close();
            }
        }
    }


    public static void main(String[] args) {
        HelloClientDemo client = new HelloClientDemo();
        client.startClient("Jimmy");
    }
}

 

 

 

HelloServerDemo

package com.kedacom.demo.thriftDemo;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TJSONProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;

public class HelloServerDemo {
    public static final int SERVER_PORT = 8090;

    public void startServer() {
        try {
            System.out.println("HelloWorld TSimpleServer start ....");

            TProcessor tprocessor = new HelloWorldService.Processor<HelloWorldService.Iface>(new HelloWorldImpl());
            TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
            TServer.Args tArgs = new TServer.Args(serverTransport);
            tArgs.processor(tprocessor);
            tArgs.protocolFactory(new TBinaryProtocol.Factory());
            // tArgs.protocolFactory(new TCompactProtocol.Factory());
            // tArgs.protocolFactory(new TJSONProtocol.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) {
        HelloServerDemo server = new HelloServerDemo();
        server.startServer();
    }
}

 

HelloWorldImpl

package com.kedacom.demo.thriftDemo;
import org.apache.thrift.TException;
public class HelloWorldImpl implements HelloWorldService.Iface {

    public HelloWorldImpl() {
    }

    public String sayHello(String username) throws TException {
        // TODO Auto-generated method stub
        return "Hi," + username + " welcome,. this is Thrift demo!";
    }
}

 

至此咱們的java版的thrift的服務端和客戶端就完成了

執行  HelloServerDemo 顯示 HelloWorld TSimpleServer start ....

執行  HelloClientDemo 顯示  Thrify client result =: Hi,Jimmy welcome,. this is Thrift demo!

 

其中核心邏輯實際上是在 執行類  HelloWorldImpl 裏面, server和client的類只是按照 thrift的標準來寫好邏輯便可, 服務端和客戶端的類的標準可參考官方文檔,下面咱們貼下 PHP 的客戶端實現代碼

首先咱們把第二步的 文件改爲

namespace php helloworld
service  HelloWorldService {
    string sayHello(1:string username)
}

執行thrift命令以後,會生成 gen-php 目錄

 

PHP客戶端代碼以下

#!/usr/bin/env php
<?php

namespace helloworld\php;

error_reporting(E_ALL);

//echo __DIR__; exit();

require_once '/opt/thrift_php/lib/Thrift/ClassLoader/ThriftClassLoader.php';

///**
use Thrift\ClassLoader\ThriftClassLoader;

//$GEN_DIR = realpath(dirname(__FILE__).'/..').'/gen-php';
$GEN_DIR = '/opt/thrift_php/mycode/gen-php';

$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', '/opt/thrift_php/lib');  //這個是thrift源碼下載以後,這個目錄thrift-0.9.3/lib/抽離出來的
//$loader->registerNamespace('Thrift', __DIR__ . '/../../lib/php/lib');
//$loader->registerDefinition('shared', $GEN_DIR);
$loader->registerDefinition('helloworld', $GEN_DIR);
$loader->register();



use Thrift\Protocol\TBinaryProtocol;
use Thrift\Transport\TSocket;
use Thrift\Transport\THttpClient;
use Thrift\Transport\TBufferedTransport;
use Thrift\Exception\TException;
//**/


//$socket = new TSocket('localhost', 8090); 
$socket = new TSocket('192.168.17.1', 8090); 
$transport = new TBufferedTransport($socket, 1024, 1024);
$protocol = new TBinaryProtocol($transport);
$client = new \helloworld\HelloWorldServiceClient($protocol);
//print_r($client);

$transport->open();
$str = $client->sayHello("jimmyxx");
echo $str;

$transport->close();

其中 $socket = new TSocket('192.168.17.1', 8090);  這句是服務端的IP地址和運行端口, 直接在linux下 PHP 執行此文件,顯示   Hi,jimmyxx welcome,. this is Thrift demo! 成功調用了java的服務端代碼, 是否是能感受到一點點跨編程語言的遠程RPC調用的魅力所在呢? 呵呵~~~ 範例簡單明瞭,應用到咱們實際項目裏面仍是要根據項目的具體狀況進行一下架構設計, 好比咱們就把PHP的客戶端,服務端都集成在咱們的MVC框架裏面去了。

源碼地址請訪問github: https://github.com/halokid/thrift-java-php,  有用的話,記得star或者fork一下哦

相關文章
相關標籤/搜索