基于上一篇博客,安装thrift complier之后,就需要进行跑跑程序,来看看是否如同预期的那种效果。

前面的thrift compiler的主要作用,其实就是为了IDL的,就是防止客户端和服务端的接口定义不同,基于IDL操作,最大限度的满足高效准确的实现服务的定义和实现。

1. 首先定义.thrift扩展名的文件,有tutorial.thrift和shared.thrift,其内容如下:

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 dart shared
namespace java shared
namespace perl shared
namespace php shared
namespace haxe shared struct SharedStruct {
: i32 key
: string value
} service SharedService {
SharedStruct getStruct(: i32 key)
}

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
* i8 (byte) Signed 8-bit integer
* 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 dart 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 =
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 = ,
SUBTRACT = ,
MULTIPLY = ,
DIVIDE =
} /**
* 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 {
: i32 num1 = ,
: i32 num2,
: Operation op,
: optional string comment,
} /**
* Structs can also be exceptions, if they are nasty.
*/
exception InvalidOperation {
: i32 whatOp,
: 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(:i32 num1, :i32 num2), i32 calculate(:i32 logid, :Work w) throws (: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.
*/

2. 在这两个thrift文件所在的目录下执行java接口文件的定义。

 [root@CloudGame thrift-demo]# ll
total
-rw-r--r--. root root Oct : shared.thrift
-rw-r--r--. root root Oct : tutorial.thrift
[root@CloudGame thrift-demo]# thrift -r --gen java tutorial.thrift
[WARNING:/home/water/Work/thrift-demo/shared.thrift:] No generator named 'dart' could be found!
[WARNING:/home/water/Work/thrift-demo/tutorial.thrift:] No generator named 'dart' could be found!
[root@CloudGame thrift-demo]#
[root@CloudGame thrift-demo]# thrift -r --gen java shared.thrift
[WARNING:/home/water/Work/thrift-demo/shared.thrift:] No generator named 'dart' could be found!

最后,你会看到一个gen-java的目录出现:

 [root@CloudGame thrift-demo]# ll
total
drwxr-xr-x. root root Oct : gen-java
-rw-r--r--. root root Oct : shared.thrift
-rw-r--r--. root root Oct : tutorial.thrift
 [root@CloudGame thrift-demo]# tree gen-java
gen-java
├── shared
│   ├── SharedService.java
│   └── SharedStruct.java
└── tutorial
├── Calculator.java
├── InvalidOperation.java
├── Operation.java
├── tutorialConstants.java
└── Work.java directories, files

3. 创建java工程,我这里用的是eclipse下的maven项目,工程创建好后,将gen-java目录下的相关java文件copy到刚才创建出来的maven工程的java目录下。

最后,将thrift的tutorial链接下,将相关的JavaClient.java以及JavaServer.java文件还有CalculatorHandler.java拷贝到maven工程下面。

注意,按照官方的tutorial来操作,是没有CalculatorHandler.java这个文件的,需要从thrift-0.9.3 (我的版本是这个,根据自己的版本不同,适当调整)解压目录中的tutorial下面的java目录下找到这个文件,拷贝到公程中相关目录下 (src/main/java/tutorial/)

4. 在JavaServer.java文件内执行run java application, 结果,出错了!

 Starting the simple server...
org.apache.thrift.transport.TTransportException: Error creating the transport
at org.apache.thrift.transport.TSSLTransportFactory.createSSLContext(TSSLTransportFactory.java:)
at org.apache.thrift.transport.TSSLTransportFactory.getServerSocket(TSSLTransportFactory.java:)
at server.JavaServer.secure(JavaServer.java:)
at server.JavaServer$.run(JavaServer.java:)
at java.lang.Thread.run(Thread.java:)
Caused by: java.io.IOException: Could not load file: ../../lib/java/test/.keystore
at org.apache.thrift.transport.TSSLTransportFactory.getStoreAsStream(TSSLTransportFactory.java:)
at org.apache.thrift.transport.TSSLTransportFactory.createSSLContext(TSSLTransportFactory.java:)
... more

注意,代码中涉及到两个方案,server运行有simple和secure两种实现,simple就不多说了,看看基于SSL的安全解决方案,需要公钥.truststore和私钥.keystore文件。这个嘛,在linux环境下,也比较简单解决,看看keytool,可以搞定。 关于keytool就不多说,google之。

 [root@CloudGame java]# keytool
Key and Certificate Management Tool Commands: -certreq Generates a certificate request
-changealias Changes an entry's alias
-delete Deletes an entry
-exportcert Exports certificate
-genkeypair Generates a key pair
-genseckey Generates a secret key
-gencert Generates certificate from a certificate request
-importcert Imports a certificate or a certificate chain
-importkeystore Imports one or all entries from another keystore
-keypasswd Changes the key password of an entry
-list Lists entries in a keystore
-printcert Prints the content of a certificate
-printcertreq Prints the content of a certificate request
-printcrl Prints the content of a CRL file
-storepasswd Changes the store password of a keystore Use "keytool -command_name -help" for usage of command_name
[root@CloudGame java]# keytool -genkeypair -alias certificatekey -keyalg RSA -validity 36500 -keystore .keystore
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]: shihu cheng
What is the name of your organizational unit?
[Unknown]: tk
What is the name of your organization?
[Unknown]: tk
What is the name of your City or Locality?
[Unknown]: wuhan
What is the name of your State or Province?
[Unknown]: hubei
What is the two-letter country code for this unit?
[Unknown]:
Is CN=shihu cheng, OU=tk, O=tk, L=wuhan, ST=hubei, C= correct?
[no]: y Enter key password for <certificatekey>
(RETURN if same as keystore password):
Re-enter new password:

这里,密码一定要记得哟,是私钥的密码。在server运行的时候,需要这个信息。

上面是私钥的生成,接下来看看证书的生成过程。

 [root@CloudGame java]# keytool -export -alias certificatekey -keystore .keystore -rfc -file server.cer
Enter keystore password:
Certificate stored in file <server.cer>

最后,利用证书生成公钥。

 [root@CloudGame java]# keytool -import -alias certificatekey -file server.cer -keystore .truststore
Enter keystore password:
Re-enter new password:
Owner: CN=shihu cheng, OU=tk, O=tk, L=wuhan, ST=hubei, C=
Issuer: CN=shihu cheng, OU=tk, O=tk, L=wuhan, ST=hubei, C=
Serial number: 7b031382
Valid from: Sat Oct :: HKT until: Mon Sep :: HKT
Certificate fingerprints:
MD5: ::F8:BF:::8C:3D:B1:::A7::3F:B0:EC
SHA1: D8::EE:::A0::::D8::7D:7E::C5:9B:::B1:
SHA256: F5:9B:DE::2D:3B::7E:B8:0B:3A:1C::A2:::D4::B4:D8:C4::AF::3B:::::::E1
Signature algorithm name: SHA256withRSA
Version: Extensions: #: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
: 8D F8 1F 2D DD 2C E5 7ad..r.-.,.HB.d.
: 4E DC EA N..y
]
] Trust this certificate? [no]: y
Certificate was added to keystore

将上面生成的私钥.keystore拷贝到maven工程目录的server目录下,将公钥.truststore拷贝到maven工程的client目录下,修改JavaClient.java以及JavaServer.java相关的代码如下:

 /*
* 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.
*/ package client; // Generated code
import tutorial.*;
import shared.*; import org.apache.thrift.TException;
import org.apache.thrift.transport.TSSLTransportFactory;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol; public class JavaClient {
public static void main(String [] args) { if (args.length != ) {
System.out.println("Please enter 'simple' or 'secure'");
System.exit();
} try {
TTransport transport;
if (args[].contains("simple")) {
transport = new TSocket("localhost", );
transport.open();
}
else {
/*
* Similar to the server, you can use the parameters to setup client parameters or
* use the default settings. On the client side, you will need a TrustStore which
* contains the trusted certificate along with the public key.
* For this example it's a self-signed cert.
*/
TSSLTransportParameters params = new TSSLTransportParameters();
params.setTrustStore("./src/main/java/client/.truststore", "shihuc", "SunX509", "JKS");
/*
* Get a client transport instead of a server transport. The connection is opened on
* invocation of the factory method, no need to specifically call open()
*/
transport = TSSLTransportFactory.getClientSocket("localhost", , , params);
} TProtocol protocol = new TBinaryProtocol(transport);
Calculator.Client client = new Calculator.Client(protocol); perform(client); transport.close();
} catch (TException x) {
x.printStackTrace();
}
} private static void perform(Calculator.Client client) throws TException
{
client.ping();
System.out.println("ping()"); int sum = client.add(,);
System.out.println("1+1=" + sum); Work work = new Work(); work.op = Operation.DIVIDE;
work.num1 = ;
work.num2 = ;
try {
int quotient = client.calculate(, work);
System.out.println("Whoa we can divide by 0");
} catch (InvalidOperation io) {
System.out.println("Invalid operation: " + io.why);
} work.op = Operation.SUBTRACT;
work.num1 = ;
work.num2 = ;
try {
int diff = client.calculate(, work);
System.out.println("15-10=" + diff);
} catch (InvalidOperation io) {
System.out.println("Invalid operation: " + io.why);
} SharedStruct log = client.getStruct();
System.out.println("Check log: " + log.value);
}
}
 /*
* 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.
*/ package server;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TServer.Args;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.transport.TSSLTransportFactory;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters; // Generated code
import tutorial.*;
import shared.*; import java.util.HashMap; 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();
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("./src/main/java/server/.keystore", "shihuc", 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(, , 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();
}
}
}

最后,再次运行JavaServer.java,得到下面的信息就对了!

 Starting the simple server...
Starting the secure server...

然后,配置eclipse的运行参数arguments为secure,运行JavaClient.java,得到下面的信息:

 ping()
+=
Invalid operation: Cannot divide by
-=
Check log:

到此,一个简单的thrift java语言的RPC程序就算是跑通了。

这里演示用的maven工程代码,可以在我的github上下载,作为参考,学习交流。

thrift demo的更多相关文章

  1. win7环境下,golang thrift demo代码编译不通过

    用官方的教程代码:http://thrift.apache.org/tutorial/go 用网友提供的代码:Golang RPC 之 Thrift 都出现如下情况 状况1: 编辑器中就会提醒 Can ...

  2. C# Apache Thrift Demo

    转载至 https://headsigned.com/posts/csharp-apache-thrift-demo/ This demo application shows how to imple ...

  3. python thrift demo

    简介Thrift最初由Facebook研发,主要用于各个服务之间的RPC通信,支持跨语言,常用的语言比如C++, Java, Python, PHP, Ruby, Erlang, Perl, Hask ...

  4. go thrift demo

    接口:https://gowalker.org/github.com/apache/thrift/lib/go/thrift 参考文件:https://cong.im/2018/05/14/other ...

  5. Thrift入门及Java实例演示<转载备用>

    Thrift入门及Java实例演示 作者: Michael 日期: 年 月 日 •概述 •下载配置 •基本概念 .数据类型 .服务端编码基本步骤 .客户端编码基本步骤 .数据传输协议 •实例演示(ja ...

  6. RPC学习----Thrift快速入门和Java简单示例

    一.什么是RPC? RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议. RPC协议 ...

  7. Thrift入门及Java实例演示

    目录: 概述 下载配置 基本概念 数据类型 服务端编码基本步骤 客户端编码基本步骤 数据传输协议 实例演示(java) thrift生成代码 实现接口Iface TSimpleServer服务模型 T ...

  8. Apache Thrift学习之一(入门及Java实例演示)

    目录: 概述 下载配置 基本概念 数据类型 服务端编码基本步骤 客户端编码基本步骤 数据传输协议 实例演示(java) thrift生成代码 实现接口Iface TSimpleServer服务模型 T ...

  9. 使用Thrift RPC编写程序(服务端和客户端)

    1. Thrift类介绍 Thrift代码包(位于thrift-0.6.1/lib/cpp/src)有以下几个目录: concurrency:并发和时钟管理方面的库processor:Processo ...

随机推荐

  1. SSO之CAS总结

    1.采用kerberos原理 2.特点,经纪人模式即需要sso的所有用户账号要集中在一起 3.安全性保证方法: 关键就是保证TS和TGC的安全. 3.1)TS生成是采用足够随机算法,一次性使用,设置有 ...

  2. null和undefined

    null表示"没有对象",即该处不应该有值.典型用法是: (1) 作为函数的参数,表示该函数的参数不是对象. (2) 作为对象原型链的终点. undefined表示"缺少 ...

  3. Linux 下安装pip

    安装pip 使用脚本安装和升级pip 要安装或升级pip,需要下载 get-pip.py. 地址:https://bootstrap.pypa.io/get-pip.py 然后运行以下命令 (需要管理 ...

  4. iOS应用之间跳转

    本篇博文将涉及到以下知识点: app应用跳转的原理解析 如何实现两个app应用之间的跳转 如何实现两个app之间跳转到指定界面 二.应用跳转原理 相信从一个应用跳转到另一个应用大家并不陌生,最常见的莫 ...

  5. 读javascript高级程序设计12-HTML5脚本编程

    一.跨文档消息传递(XDM) 1.发送消息 postMessage(msg,domain)用于发送跨文档消息.第一个参数是要传递的消息内容,第二个参数表示接收方来自哪个域.第二个参数有助于提高安全性, ...

  6. javaee包含的服务和组件

    参考自 http://blog.itpub.net/29990276/viewspace-1318551/

  7. PowerMock遇到的问题——5

    在做单元测试时,有时在一个方法中会调用这个类的其他私有方法,那么如何指定这些方法的返回值呢? 解决方法:用 createPartialMock 具体用法如下: TestClass test=Power ...

  8. Nginx反向代理关于端口的问题

      Nginx反向代理关于端口的问题   http://www.cnblogs.com/likehua/p/4056625.html Nginx默认反向后的端口为80,因此存在被代理后的端口为80的问 ...

  9. 读取配置文件 PropertyPlaceholderConfigurer 的配置与使用

    public class SpringPropertyConfigurer extends PropertyPlaceholderConfigurer { private static Map< ...

  10. ios中tableSection的颜色

    ios中tableSection的颜色可以用: @"0xf5f5f5",有个第三方库 #import "UIColor+expanded.h"可以支持十六进制取 ...