博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用thrift实现了Javaserver和nodejsclient之间的跨平台通信
阅读量:6906 次
发布时间:2019-06-27

本文共 15885 字,大约阅读时间需要 52 分钟。

1. 简介

          

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

2. 下载与安装

Thrift眼下最高0.9.2,地址:

注意,我们要把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
Map from one type to another * list
Ordered list of one type * set
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 sharednamespace d share // "shared" would collide with the eponymous D keyword.namespace java sharednamespace perl sharednamespace php sharednamespace haxe sharedstruct 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 codeimport tutorial.Calculator;import tutorial.InvalidOperation;import tutorial.Work;public class CalculatorHandler implements Calculator.Iface {	private HashMap
log; public CalculatorHandler() { log = new HashMap
(); } 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 codeimport 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

org.apache.thrift
libthrift
0.9.2
org.slf4j
slf4j-api
1.6.1
org.slf4j
log4j-over-slf4j
1.6.1
5、用java文件夹下的keytool生成证书;

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

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

params.setKeyStore("c:/.mykeystore", "jinking", 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 connectionvar 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之间的跨平台通信;

你可能感兴趣的文章
java同步与多线程浅析
查看>>
黑我们程序员!
查看>>
单例模式
查看>>
寻找JavaFX,SceneBuilder崩溃之谜
查看>>
window.location地址对应的方法
查看>>
图解设计模式:原型(Prototype)
查看>>
IT系统集成讲座[【1】
查看>>
Mysql 慢查询和慢查询日志分析
查看>>
tomcat与nginx的整合
查看>>
IIS是如何处理ASP.NET请求的
查看>>
HTTP错误大全
查看>>
内核启动过程
查看>>
JSplitPane分割线固定问题
查看>>
递推公式-HDOJ2041
查看>>
android中listview的getView方法不调用的一种情况
查看>>
HTTP socket 类
查看>>
两个有用的宏:“禁止类成员复制”以及“禁止隐式构造”
查看>>
如何创建OpenCart主题/模板
查看>>
DES加密解密 JAVA与.NET互通程序代码
查看>>
springframework shedular task
查看>>