• 使用thrift实现了Javaserver和nodejsclient之间的跨平台通信


    1. 简介

              

    thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎。以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。  


    2. 下载与安装


    Thrift眼下最高0.9.2,地址:http://archive.apache.org/dist/thrift/

    注意,我们要把exe和tar文件都下载下来,exe用来编译你的thrift中间语言。而tar解压后,我们能够看到csharp,php,java,js等多种开发语言的实例代码,对我们非常有帮助的,下载最新版。当中包括lib文件库。包括各种语言须要的类库。

    下载之后,我们把exe文件可放在C盘,建个Thrift文件夹,把它放入。然后能够配置一下环境变量;将thrift的文件夹路径加入到path变量中;

    3. 编写thrift文件


    首先编写:tutorial.thrift

    /*
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements. See the NOTICE file
     * distributed with this work for additional information
     * regarding copyright ownership. The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the
     * "License"); you may not use this file except in compliance
     * with the License. You may obtain a copy of the License at
     *
     *   http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing,
     * software distributed under the License is distributed on an
     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     * KIND, either express or implied. See the License for the
     * specific language governing permissions and limitations
     * under the License.
     */
    
    # Thrift Tutorial
    # Mark Slee (mcslee@facebook.com)
    #
    # This file aims to teach you how to use Thrift, in a .thrift file. Neato. The
    # first thing to notice is that .thrift files support standard shell comments.
    # This lets you make your thrift file executable and include your Thrift build
    # step on the top line. And you can place comments like this anywhere you like.
    #
    # Before running this file, you will need to have installed the thrift compiler
    # into /usr/local/bin.
    
    /**
     * The first thing to know about are types. The available types in Thrift are:
     *
     *  bool        Boolean, one byte
     *  byte        Signed byte
     *  i16         Signed 16-bit integer
     *  i32         Signed 32-bit integer
     *  i64         Signed 64-bit integer
     *  double      64-bit floating point value
     *  string      String
     *  binary      Blob (byte array)
     *  map<t1,t2>  Map from one type to another
     *  list<t1>    Ordered list of one type
     *  set<t1>     Set of unique elements of one type
     *
     * Did you also notice that Thrift supports C style comments?

    */ // Just in case you were wondering... yes. We support simple C comments too. /** * Thrift files can reference other Thrift files to include common struct * and service definitions. These are found using the current path, or by * searching relative to any paths specified with the -I compiler flag. * * Included objects are accessed using the name of the .thrift file as a * prefix. i.e. shared.SharedObject */ include "shared.thrift" /** * Thrift files can namespace, package, or prefix their output in various * target languages. */ namespace cpp tutorial namespace d tutorial namespace java tutorial namespace php tutorial namespace perl tutorial namespace haxe tutorial /** * Thrift lets you do typedefs to get pretty names for your types. Standard * C style here. */ typedef i32 MyInteger /** * Thrift also lets you define constants for use across languages. Complex * types and structs are specified using JSON notation. */ const i32 INT32CONSTANT = 9853 const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'} /** * You can define enums, which are just 32 bit integers. Values are optional * and start at 1 if not supplied, C style again. */ enum Operation { ADD = 1, SUBTRACT = 2, MULTIPLY = 3, DIVIDE = 4 } /** * Structs are the basic complex data structures. They are comprised of fields * which each have an integer identifier, a type, a symbolic name, and an * optional default value. * * Fields can be declared "optional", which ensures they will not be included * in the serialized output if they aren't set. Note that this requires some * manual management in some languages. */ struct Work { 1: i32 num1 = 0, 2: i32 num2, 3: Operation op, 4: optional string comment, } /** * Structs can also be exceptions, if they are nasty. */ exception InvalidOperation { 1: i32 whatOp, 2: string why } /** * Ahh, now onto the cool part, defining a service. Services just need a name * and can optionally inherit from another service using the extends keyword. */ service Calculator extends shared.SharedService { /** * A method definition looks like C code. It has a return type, arguments, * and optionally a list of exceptions that it may throw. Note that argument * lists and exception lists are specified using the exact same syntax as * field lists in struct or exception definitions. */ void ping(), i32 add(1:i32 num1, 2:i32 num2), i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch), /** * This method has a oneway modifier. That means the client only makes * a request and does not listen for any response at all. Oneway methods * must be void. */ oneway void zip() } /** * That just about covers the basics. Take a look in the test/ folder for more * detailed examples. After you run this file, your generated code shows up * in folders with names gen-<language>. The generated code isn't too scary * to look at. It even has pretty indentation. */


    附上shared.thrift
    /*
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements. See the NOTICE file
     * distributed with this work for additional information
     * regarding copyright ownership. The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the
     * "License"); you may not use this file except in compliance
     * with the License. You may obtain a copy of the License at
     *
     *   http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing,
     * software distributed under the License is distributed on an
     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     * KIND, either express or implied. See the License for the
     * specific language governing permissions and limitations
     * under the License.
     */
    
    /**
     * This Thrift file can be included by other Thrift files that want to share
     * these definitions.
     */
    
    namespace cpp shared
    namespace d share // "shared" would collide with the eponymous D keyword.
    namespace java shared
    namespace perl shared
    namespace php shared
    namespace haxe shared
    
    struct SharedStruct {
      1: i32 key
      2: string value
    }
    
    service SharedService {
      SharedStruct getStruct(1: i32 key)
    }



    2、输入编译命令,将接口文件编译相应的语言java、nodejs。

    >thrift -r --gen java tutorial.thrift                                     

    >thrift -r --gen js:node tutorial.thrift                                

    3、能够在当前文件夹下看到相应生成的文件夹gen-java、gen-nodejs;

        

    4. 创建Java语言的server


    1、在eclipse新建MavenProject名为thrift


    2、创建CalculatorHandler.java和JavaServer.java文件。代码例如以下: 

    CalculatorHandler.java

    package tutorial.impl;
    
    /*
     * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
     * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
     * License. You may obtain a copy of the License at
     * 
     * http://www.apache.org/licenses/LICENSE-2.0
     * 
     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
     * specific language governing permissions and limitations under the License.
     */
    
    import java.util.HashMap;
    
    import shared.SharedStruct;
    // Generated code
    import tutorial.Calculator;
    import tutorial.InvalidOperation;
    import tutorial.Work;
    
    public class CalculatorHandler implements Calculator.Iface {
    
    	private HashMap<Integer, SharedStruct> log;
    
    	public CalculatorHandler() {
    		log = new HashMap<Integer, SharedStruct>();
    	}
    
    	public void ping() {
    		System.out.println("ping()");
    	}
    
    	public int add(int n1, int n2) {
    		System.out.println("add(" + n1 + "," + n2 + ")");
    		return n1 + n2;
    	}
    
    	public int calculate(int logid, Work work) throws InvalidOperation {
    		System.out.println("calculate(" + logid + ", {" + work.op + "," + work.num1 + "," + work.num2 + "})");
    		int val = 0;
    		switch (work.op) {
    		case ADD:
    			val = work.num1 + work.num2;
    			break;
    		case SUBTRACT:
    			val = work.num1 - work.num2;
    			break;
    		case MULTIPLY:
    			val = work.num1 * work.num2;
    			break;
    		case DIVIDE:
    			if (work.num2 == 0) {
    				InvalidOperation io = new InvalidOperation();
    				io.whatOp = work.op.getValue();
    				io.why = "Cannot divide by 0";
    				throw io;
    			}
    			val = work.num1 / work.num2;
    			break;
    		default:
    			InvalidOperation io = new InvalidOperation();
    			io.whatOp = work.op.getValue();
    			io.why = "Unknown operation";
    			throw io;
    		}
    
    		SharedStruct entry = new SharedStruct();
    		entry.key = logid;
    		entry.value = Integer.toString(val);
    		log.put(logid, entry);
    
    		return val;
    	}
    
    	public SharedStruct getStruct(int key) {
    		System.out.println("getStruct(" + key + ")");
    		return log.get(key);
    	}
    
    	public void zip() {
    		System.out.println("zip()");
    	}
    
    }
    

    3.JavaServer文件代码

    package Server;
    
    /*
     * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
     * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
     * License. You may obtain a copy of the License at
     * 
     * http://www.apache.org/licenses/LICENSE-2.0
     * 
     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
     * specific language governing permissions and limitations under the License.
     */
    
    import org.apache.thrift.server.TServer;
    import org.apache.thrift.server.TServer.Args;
    import org.apache.thrift.server.TSimpleServer;
    import org.apache.thrift.transport.TSSLTransportFactory;
    import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters;
    import org.apache.thrift.transport.TServerSocket;
    import org.apache.thrift.transport.TServerTransport;
    
    // Generated code
    import tutorial.Calculator;
    import tutorial.impl.CalculatorHandler;
    
    public class JavaServer {
    
    	public static CalculatorHandler handler;
    
    	public static Calculator.Processor processor;
    
    	public static void main(String[] args) {
    		try {
    			handler = new CalculatorHandler();
    			processor = new Calculator.Processor(handler);
    
    			Runnable simple = new Runnable() {
    				public void run() {
    					simple(processor);
    				}
    			};
    			Runnable secure = new Runnable() {
    				public void run() {
    					secure(processor);
    				}
    			};
    
    			new Thread(simple).start();
    			new Thread(secure).start();
    		} catch (Exception x) {
    			x.printStackTrace();
    		}
    	}
    
    	public static void simple(Calculator.Processor processor) {
    		try {
    			TServerTransport serverTransport = new TServerSocket(9090);
    			TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));
    
    			// Use this for a multithreaded server
    			// TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor));
    
    			System.out.println("Starting the simple server...");
    			server.serve();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	public static void secure(Calculator.Processor processor) {
    		try {
    			/*
    			 * Use TSSLTransportParameters to setup the required SSL parameters. In this example we are setting the keystore
    			 * and the keystore password. Other things like algorithms, cipher suites, client auth etc can be set.
    			 */
    			TSSLTransportParameters params = new TSSLTransportParameters();
    			// The Keystore contains the private key
    			params.setKeyStore("c:/.mykeystore", "jinking", null, null);
    
    			/*
    			 * Use any of the TSSLTransportFactory to get a server transport with the appropriate SSL configuration. You can
    			 * use the default settings if properties are set in the command line. Ex: -Djavax.net.ssl.keyStore=.keystore and
    			 * -Djavax.net.ssl.keyStorePassword=thrift
    			 * 
    			 * Note: You need not explicitly call open(). The underlying server socket is bound on return from the factory
    			 * class.
    			 */
    			TServerTransport serverTransport = TSSLTransportFactory.getServerSocket(9091, 0, null, params);
    			TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));
    
    			// Use this for a multi threaded server
    			// TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor));
    
    			System.out.println("Starting the secure server...");
    			server.serve();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    4、配置须要的lib类库。编辑pom.xml文件,必备的类库有libthrift和slf4j-api

    		<dependency>
    			<groupId>org.apache.thrift</groupId>
    			<artifactId>libthrift</artifactId>
    			<version>0.9.2</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-api</artifactId>
    			<version>1.6.1</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>log4j-over-slf4j</artifactId>
    			<version>1.6.1</version>
    		</dependency>

    5、用java文件夹下的keytool生成证书;

    >keytool -certreq -keyalg RSA -alias myalias -file certreq.txt -keystore c:.mykeystore

    代码对应的改动成你生成的秘钥,红色字体标出;

    params.setKeyStore("c:/.mykeystore", <span style="color:#ff0000;">"jinking"</span>, null, null);

    6、执行javaServer.java文件,能够看到例如以下界面;


    5. 创建nodejs版的client


    1、首先就是要搭建nodejs环境和npm和express、安装相应模块。这个能够去网上搜索一下。不在此叙述。
    可能会报错:Error: Cannot find module 'thrift'  和 Error: Cannot find module 'node-int64' 、Error: Cannot find module 'q'
    则须要输入以下的文件夹安装相应的模块:
    npm install -g node-int64  和  npm install -g thrift 、  npm install -g q
    2、新建project文件夹client;
    3、讲lib下的nodejs类库和gen-nodejs,复制到根文件夹下。路径例如以下:


    4、创建NodeClient.js文件

    /*
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements. See the NOTICE file
     * distributed with this work for additional information
     * regarding copyright ownership. The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the
     * "License"); you may not use this file except in compliance
     * with the License. You may obtain a copy of the License at
     *
     *   http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing,
     * software distributed under the License is distributed on an
     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     * KIND, either express or implied. See the License for the
     * specific language governing permissions and limitations
     * under the License.
     */
    
    var thrift = require('./thrift');
    var ThriftTransports = require('./thrift/transport');
    var ThriftProtocols = require('./thrift/protocol');
    var Calculator = require('./gen-nodejs/Calculator');
    var ttypes = require('./gen-nodejs/tutorial_types');
    
    
    transport = ThriftTransports.TBufferedTransport()
    protocol = ThriftProtocols.TBinaryProtocol()
    
    var connection = thrift.createConnection("localhost", 9090, {
      transport : transport,
      protocol : protocol
    });
    
    connection.on('error', function(err) {
      assert(false, err);
    });
    
    // Create a Calculator client with the connection
    var client = thrift.createClient(Calculator, connection);
    
    
    client.ping(function(err, response) {
      console.log('ping()');
    });
    
    
    client.add(1,1, function(err, response) {
      console.log("1+1=" + response);
    });
    
    
    work = new ttypes.Work();
    work.op = ttypes.Operation.DIVIDE;
    work.num1 = 1;
    work.num2 = 0;
    
    client.calculate(1, work, function(err, message) {
      if (err) {
        console.log("InvalidOperation " + err);
      } else {
        console.log('Whoa? You know how to divide by zero?');
      }
    });
    
    work.op = ttypes.Operation.SUBTRACT;
    work.num1 = 15;
    work.num2 = 10;
    
    client.calculate(1, work, function(err, message) {
      console.log('15-10=' + message);
    
      client.getStruct(1, function(err, message){
        console.log('Check log: ' + message.value);
    
        //close the connection once we're done
        connection.end();
      });
    });


    5、输入:>node NodeClient.js
    6、nodejsclient命令行窗体显示:


    7、Javaserver端显示:


    8、大功告成。

    使用thrift框架实现了Java和nodejs之间的跨平台通信;

  • 相关阅读:
    JavaScript中的事件循环
    CSS布局
    Tomcat相关
    C#参数中ref和out的区别
    angular启动4200端口后,如何停止监听4200端口
    表联接(交叉连接,内联,外联)
    如何使用vs自带的反编译工具Lldasm
    软件架构需要注意的几点,待补充。。。
    SqlServer中With(NOLOCK)
    TypeScript preview
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/6806233.html
Copyright © 2020-2023  润新知