From the Thrift website: 来自 Thrift 网站:
Thrift 是一个用于可扩展跨语言服务开发的软件框架。它结合了软件栈和代码生成引擎,构建能够在 C++、Java、Python、PHP、Ruby、Erlang、Perl、Haskell、C#、Cocoa、JavaScript、Node.js、Smalltalk 和 OCaml 之间高效且无缝工作的服务。
Thrift is clearly abundant in features. What is sorely lacking though is good
documentation. This guide is an attempt to fill that hole. But note that this is
a reference guide — for a step-by-step example on how to use Thrift, refer to
the Thrift tutorial.
Thrift 显然功能丰富。但严重缺乏的是良好的文档。本指南试图填补这一空白。但请注意,这只是一本参考指南——有关如何使用 Thrift 的逐步示例,请参阅 Thrift 教程。
Many aspects of the structure and organization of this guide have been borrowed
from the (excellent)
Google Protocol
Buffer Language Guide. I thank the authors of that document.
本指南的结构和组织的许多方面借鉴了(优秀的)Google 协议缓冲区语言指南。感谢该文档的作者们。
A PDF version is also available.
也提供了 PDF 版本。
Copyright © 2013 Diwaker Gupta
版权 © 2013 Diwaker Gupta
This work is licensed under the
Creative Commons
Attribution-NonCommercial 3.0
Unported License.
本作品采用知识共享署名-非商业性使用 3.0 未本地化许可协议授权。
I welcome feedback and contributions to this guide. You can find the
source code
over at GitHub. Alternatively, you can file a
bug.
我欢迎对本指南的反馈和贡献。您可以在 GitHub 上找到源代码。或者,您也可以提交一个错误报告。
I thank the authors of Thrift for the software, the authors of the Google
Protocol Buffer documentation for the inspiration and the Thrift community for
the feedback. Special thanks to Dave Engberg from Evernote for his input.
感谢 Thrift 的作者提供软件,感谢 Google Protocol Buffer 文档的作者带来的启发,以及 Thrift 社区的反馈。特别感谢 Evernote 的 Dave Engberg 提供的宝贵意见。
I’m an open source geek and a software architect. I blog over at
Floating Sun and you can find more about me
here.
我是一个开源极客和软件架构师。我在 Floating Sun 上写博客,你可以在这里了解更多关于我的信息。
Language Reference 语言参考
Types 类型
The Thrift type system consists of pre-defined base types, user-defined structs,
container types, exceptions and service definitions.
Thrift 类型系统由预定义的基本类型、用户定义的结构体、容器类型、异常和服务定义组成。
Base Types 基本类型
-
bool: A boolean value (true or false), one byte
bool: 布尔值(真或假),占用一个字节 -
byte: A signed byte
byte: 有符号字节 -
i16: A 16-bit signed integer
i16: 16 位有符号整数 -
i32: A 32-bit signed integer
i32: 32 位有符号整数 -
i64: A 64-bit signed integer
i64:一个 64 位有符号整数 -
double: A 64-bit floating point number
double:一个 64 位浮点数 -
binary: A byte array
binary:一个字节数组 -
string: Encoding agnostic text or binary string
string:编码无关的文本或二进制字符串
Note that Thrift does not support unsigned integers because they have no direct
translation to native (primitive) types in many of Thrift’s target languages.
请注意,Thrift 不支持无符号整数,因为它们在 Thrift 的许多目标语言中没有直接对应的本地(原始)类型。
Containers 容器
Thrift containers are strongly typed containers that map to the most commonly
used containers in popular programming languages. They are annotated using the
Java Generics style. There are three containers types available:
Thrift 容器是强类型容器,映射到流行编程语言中最常用的容器。它们使用 Java 泛型风格进行注解。共有三种容器类型可用:
-
list<t1>: An ordered list of elements of type t1. May contain duplicates.
list:一个有序的 t1 类型元素列表。可以包含重复元素。 -
set<t1>: An unordered set of unique elements of type t1.
set:一种无序的唯一元素集合,元素类型为 t1。 -
map<t1,t2>: A map of strictly unique keys of type t1 to values of type t2.
map:一个映射,键为类型 t1 的严格唯一键,值为类型 t2。
Types used in containers may be any valid Thrift type (including structs and
exceptions) excluding services.
容器中使用的类型可以是任何有效的 Thrift 类型(包括结构体和异常),但不包括服务。
Structs and Exceptions 结构体和异常
A Thrift struct is conceptually similar to a C struct — a convenient way of
grouping together (and encapsulating) related items. Structs translate to
classes in object-oriented languages.
Thrift 结构体在概念上类似于 C 语言的结构体——一种方便地将相关项目组合在一起(并封装)的方式。结构体在面向对象语言中转换为类。
Exceptions are syntactically and functionally equivalent to structs except that
they are declared using the exception keyword instead of the struct keyword.
They differ from structs in semantics — when defining RPC services, developers
may declare that a remote method throws an exception.
异常在语法和功能上与结构体等价,但它们是使用 exception 关键字而非 struct 关键字声明的。它们在语义上与结构体不同——在定义 RPC 服务时,开发者可以声明远程方法会抛出异常。
Details on defining structs and exceptions are the subject of a
later section.
关于定义结构体和异常的详细内容将在后续章节中介绍。
Services 服务
Service definitions are semantically equivalent to defining an interface (or a
pure virtual abstract class) in object-oriented programming. The Thrift compiler
generates fully functional client and server stubs that implement the interface.
服务定义在语义上等同于在面向对象编程中定义接口(或纯虚抽象类)。Thrift 编译器生成完全功能的客户端和服务器存根来实现该接口。
Details on defining services are the subject of a later section.
关于定义服务的详细内容将在后面的章节中介绍。
Typedefs 类型定义
Thrift supports C/C++ style typedefs.
Thrift 支持 C/C++ 风格的类型定义(typedef)。
typedef i32 MyInteger //
typedef Tweet ReTweet //
Note there is no trailing semi-colon
请注意,末尾没有分号 | |
Structs can also be used in typedefs
结构体也可以用于类型定义(typedefs) |
Enums 枚举
When you’re defining a message type, you might want one of its fields to only
have one of a pre-defined list of values. For example, let’s say you want to add
a tweetType field for each Tweet, where the tweetType can be
TWEET, RETWEET, DM, or REPLY. You can do this very simply by
adding an enum to your message definition — a field with an enum type can only
have one of a specified set of constants as its value (if you try to provide a
different value, the parser will treat it like an unknown field). In the
following example we’ve added an enum called TweetType with all the possible
values, and a field of the same type:
当你定义一个消息类型时,可能希望它的某个字段只能拥有预定义列表中的某个值。例如,假设你想为每条推文添加一个 tweetType 字段,其中 tweetType 可以是 TWEET、RETWEET、DM 或 REPLY。你可以通过在消息定义中添加一个枚举来非常简单地实现这一点——枚举类型的字段只能拥有指定常量集合中的一个值(如果你尝试提供不同的值,解析器会将其视为未知字段)。在下面的示例中,我们添加了一个名为 TweetType 的枚举,包含所有可能的值,以及一个相同类型的字段:
enum TweetType {
TWEET, //
RETWEET = 2, //
DM = 0xa, //
REPLY
} //
struct Tweet {
1: required i32 userId;
2: required string userName;
3: required string text;
4: optional Location loc;
5: optional TweetType tweetType = TweetType.TWEET //
16: optional string language = "english"
}
Enums are specified C-style. Compiler assigns default values starting at 0.
枚举采用 C 风格指定。编译器默认从 0 开始分配值。 | |
You can of course, supply specific integral values for constants.
当然,你可以为常量提供具体的整数值。 | |
Hex values are also acceptable.
十六进制值也是可以接受的。 | |
Again notice no trailing semi-colon
再次注意,没有尾随的分号。 | |
Use the fully qualified name of the constant when assigning default values.
在赋予默认值时,使用常量的全限定名。 |
Note that unlike Protocol Buffers, Thrift does NOT yet support nested enums (or
structs, for that matter).
请注意,与 Protocol Buffers 不同,Thrift 目前尚不支持嵌套枚举(或结构体)。
Enumerator constants MUST be in the range of positive 32-bit integers.
枚举常量必须在正 32 位整数的范围内。
Comments 注释
Thrift supports shell-style, C-style multi-line as well as single-line Java/C++
style comments.
Thrift 支持 shell 风格、C 风格的多行注释以及单行的 Java/C++ 风格注释。
# This is a valid comment.
/*
* This is a multi-line comment.
* Just like in C.
*/
// C++/Java style single-line comments work just as well.
Namespaces 命名空间
Namespaces in Thrift are akin to namespaces in C++ or packages in Java — they
offer a convenient way of organizing (or isolating) your code. Namespaces may
also be used to prevent name clashes between type definitions.
Thrift 中的命名空间类似于 C++ 中的命名空间或 Java 中的包——它们提供了一种方便的方式来组织(或隔离)代码。命名空间还可用于防止类型定义之间的名称冲突。
Because each language has its own package-like mechanisms (e.g. Python has
modules), Thrift allows you to customize the namespace behavior on a
per-language basis:
因为每种语言都有自己的类似包的机制(例如 Python 有模块),Thrift 允许你针对每种语言自定义命名空间的行为:
namespace cpp com.example.project //
namespace java com.example.project //
Translates to namespace com { namespace example { namespace project { 翻译为命名空间 com { 命名空间 example { 命名空间 project { | |
Translates to package com.example.project 翻译为 package com.example.project |
Includes 包括
It is often useful to split up Thrift definitions in separate files to ease
maintainance, enable reuse and improve modularity/organization. Thrift allows
files to include other Thrift files. Included files are looked up in the
current directory and by searching relative to any paths specified with the -I
compiler flag.
将 Thrift 定义拆分到不同的文件中通常很有用,这样可以简化维护、实现重用并提高模块化/组织性。Thrift 允许文件包含其他 Thrift 文件。被包含的文件会在当前目录中查找,并通过相对于使用 -I 编译器标志指定的任何路径进行搜索。
Included objects are accessed using the name of the Thrift file as a prefix.
包含的对象通过使用 Thrift 文件名作为前缀来访问。
include "tweet.thrift" //
...
struct TweetSearchResult {
1: list<tweet.Tweet> tweets; //
}
File names must be quoted; again notice the absent semi-colon.
文件名必须加引号;再次注意缺少分号。 | |
Note the tweet prefix.
注意推文前缀。 |
Constants 常量
Thrift lets you define constants for use across languages. Complex types and
structs are specified using JSON notation.
Thrift 允许你定义跨语言使用的常量。复杂类型和结构体使用 JSON 表示法指定。
const i32 INT_CONST = 1234; //
const map<string,string> MAP_CONST = {"hello": "world", "goodnight": "moon"}
Semi-colon is (confusingly) optional; hex values are valid here.
分号是(令人困惑地)可选的;这里十六进制值是有效的。 |
Defining Structs 定义结构体
Structs (also known as messages in some systems) are the basic building blocks
in a Thrift IDL. A struct is composed of fields; each field has a unique
integer identifier, a type, a name and an optional default value.
结构体(在某些系统中也称为消息)是 Thrift IDL 中的基本构建块。结构体由字段组成;每个字段都有一个唯一的整数标识符、类型、名称和一个可选的默认值。
Consider a simple example. Suppose you want to build a
Twitter-like service. Here is how you might define a Tweet:
考虑一个简单的例子。假设你想构建一个类似 Twitter 的服务。以下是你可能如何定义一条推文:
struct Location { //
1: required double latitude;
2: required double longitude;
}
struct Tweet {
1: required i32 userId; //
2: required string userName; //
3: required string text;
4: optional Location loc; //
16: optional string language = "english" //
}
Every field must have a unique, positive integer identifier
每个字段必须有一个唯一的正整数标识符 | |
Fields may be marked as required or optional 字段可以标记为必填或可选 | |
Structs may contain other structs
结构体可以包含其他结构体 | |
You may specify an optional "default" value for a field
你可以为字段指定一个可选的“默认”值 | |
Multiple structs can be defined and referred to within the same Thrift file
可以在同一个 Thrift 文件中定义和引用多个结构体 |
As you can see, each field in the message definition has a unique numbered tag.
These tags are used to identify your fields in the wire format, and should not
be changed once your message type is in use.
正如您所见,消息定义中的每个字段都有一个唯一的编号标签。这些标签用于在线格式中识别您的字段,一旦您的消息类型投入使用,就不应更改这些标签。
Fields may be marked required or optional with obvious meanings for
well-formed structs. Thrift will complain if required fields have not been set
in a struct, for instance. If an optional field has not been set in the struct,
it will not be serialized over the wire. If a default value has been specified
for an optional field, the field is assigned the default value when the struct
is parsed and no value has been explicitly assigned for that field.
字段可以标记为必需或可选,对于格式良好的结构体来说含义显而易见。例如,如果必需字段未在结构体中设置,Thrift 会报错。如果可选字段未在结构体中设置,则不会被序列化传输。如果为可选字段指定了默认值,当解析结构体且该字段未被显式赋值时,该字段将被赋予默认值。
Unlike services, structs do not support inheritance, that is, a struct may not
extend other structs.
与服务不同,结构体不支持继承,也就是说,结构体不能继承其他结构体。
|
Required Is Forever 所需即永恒 You should be very careful about marking fields as required. If at some point
you wish to stop writing or sending a required field, it will be problematic to
change the field to an optional field — old readers will consider messages
without this field to be incomplete and may reject or drop them unintentionally.
You should consider writing application-specific custom validation routines for
your buffers instead. Some have come to the conclusion that using required does
more harm than good; they prefer to use only optional. However, this view is not
universal.你在将字段标记为必填时应非常小心。如果某个时候你希望停止编写或发送必填字段,将该字段更改为可选字段会带来问题——旧的接收者会认为没有该字段的消息是不完整的,可能会无意中拒绝或丢弃这些消息。你应考虑为你的缓冲区编写特定于应用程序的自定义验证程序。有些人认为使用必填字段弊大于利;他们更倾向于只使用可选字段。然而,这种观点并非普遍接受。 |
Defining Services 定义服务
While there are several popular serialization/deserialization frameworks (like
Protocol Buffers), there are few frameworks that provide out-of-the-box support
for RPC-based services across multiple languages. This is one of the major
attractions of Thrift.
虽然有几种流行的序列化/反序列化框架(如 Protocol Buffers),但很少有框架能够开箱即用地支持跨多语言的基于 RPC 的服务。这是 Thrift 的主要吸引力之一。
Think of service definitions as Java interfaces — you need to supply a name and
signatures for the methods. Optionally, a service may extend other services.
可以将服务定义看作 Java 接口——你需要提供方法的名称和签名。服务也可以选择性地继承其他服务。
The Thrift compiler will generate service interface code (for the server) and
stubs (for the client) in your chosen language. Thrift ships with RPC libraries
for most languages that you can then use to run your client and server.
Thrift 编译器将生成服务接口代码(用于服务器端)和存根代码(用于客户端),支持你选择的编程语言。Thrift 附带了大多数语言的 RPC 库,你可以使用它们来运行客户端和服务器。
service Twitter {
// 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 list are specified using the exact same syntax as
// field lists in structs.
void ping(), //
bool postTweet(1:Tweet tweet) throws (1:TwitterUnavailable unavailable), //
TweetSearchResult searchTweets(1:string query); //
// The 'oneway' modifier indicates that the client only makes a request and
// does not wait for any response at all. Oneway methods MUST be void.
oneway void zip() //
}
Confusingly, method definitions can be terminated using comma or semi-colon
令人困惑的是,方法定义可以用逗号或分号结束 | |
Arguments can be primitive types or structs
参数可以是原始类型或结构体 | |
Likewise for return types
返回类型同理 | |
void is a valid return type for functions
void 是函数的有效返回类型 |
Note that the argument lists (and exception lists) for functions are specified
exactly like structs.
注意,函数的参数列表(和异常列表)与结构体的定义方式完全相同。
Services support inheritance: a service may optionally inherit from another
service using the extends keyword.
服务支持继承:一个服务可以使用 extends 关键字可选地继承另一个服务。
|
Nested Types 嵌套类型 As of this writing, Thrift does NOT support nested type definitions. That is,
you may not define a struct (or an enum) within a struct; you may of course
use structs/enums within other structs.截至本文撰写时,Thrift 不支持嵌套类型定义。也就是说,您不能在结构体内定义另一个结构体(或枚举);当然,您可以在结构体中使用其他结构体或枚举。 |
Generated Code 生成代码
This section contains documentation for working with Thrift generated code in
various target languages. We begin by introducing the common concepts that are
used across the board — these govern how the generated code is structured and
will hopefully help you understand how to use it effectively.
本节包含有关在各种目标语言中使用 Thrift 生成代码的文档。我们首先介绍跨平台通用的基本概念——这些概念决定了生成代码的结构,并希望能帮助您有效地使用它。
Concepts 概念
Here is a pictorial view of the Thrift network stack:
下面是 Thrift 网络栈的示意图:
Thrift 网络栈
+-------------------------------------------+ | cGRE | | Server | | (single-threaded, event-driven etc) | +-------------------------------------------+ | cBLU | | Processor | | (compiler generated) | +-------------------------------------------+ | cGRE | | Protocol | | (JSON, compact etc) | +-------------------------------------------+ | cGRE | | Transport | | (raw TCP, HTTP etc) | +-------------------------------------------+
Transport 运输
The Transport layer provides a simple abstraction for reading/writing from/to
the network. This enables Thrift to decouple the underlying transport from the
rest of the system (serialization/deserialization, for instance).
传输层提供了一个用于从网络读取/写入的简单抽象。这使得 Thrift 能够将底层传输与系统的其他部分(例如序列化/反序列化)解耦。
Here are some of the methods exposed by the Transport interface:
以下是 Transport 接口公开的一些方法:
-
open 打开
-
close 关闭
-
read 读取
-
write 写
-
flush 冲水
In addition to the Transport interface above, Thrift also uses a
ServerTransport interface used to accept or create primitive transport
objects. As the name suggest, ServerTransport is used mainly on the server
side to create new Transport objects for incoming connections.
除了上述的 Transport 接口外,Thrift 还使用了一个 ServerTransport 接口,用于接受或创建原始的传输对象。顾名思义,ServerTransport 主要用于服务器端,为传入的连接创建新的 Transport 对象。
-
open 打开
-
listen 听
-
accept 接受
-
close 关闭
Here are some of the transports available for majority of the Thrift-supported
languages:
以下是大多数支持 Thrift 的语言可用的一些传输方式:
-
file: read/write to/from a file on disk
文件:从磁盘读写文件 -
http: as the name suggests
http:顾名思义
Protocol 协议
The Protocol abstraction defines a mechanism to map in-memory data structures to
a wire-format. In other words, a protocol specifies how datatypes use the
underlying Transport to encode/decode themselves. Thus the protocol
implementation governs the encoding scheme and is responsible for
(de)serialization. Some examples of protocols in this sense include JSON, XML,
plain text, compact binary etc.
协议抽象定义了一种将内存中的数据结构映射到线格式的机制。换句话说,协议指定了数据类型如何使用底层传输来编码/解码自身。因此,协议实现决定了编码方案,并负责(反)序列化。在这个意义上,一些协议的例子包括 JSON、XML、纯文本、紧凑二进制等。
Here is the Protocol interface:
这是协议接口:
writeMessageBegin(name, type, seq)
writeMessageEnd()
writeStructBegin(name)
writeStructEnd()
writeFieldBegin(name, type, id)
writeFieldEnd()
writeFieldStop()
writeMapBegin(ktype, vtype, size)
writeMapEnd()
writeListBegin(etype, size)
writeListEnd()
writeSetBegin(etype, size)
writeSetEnd()
writeBool(bool)
writeByte(byte)
writeI16(i16)
writeI32(i32)
writeI64(i64)
writeDouble(double)
writeString(string)
name, type, seq = readMessageBegin()
readMessageEnd()
name = readStructBegin()
readStructEnd()
name, type, id = readFieldBegin()
readFieldEnd()
k, v, size = readMapBegin()
readMapEnd()
etype, size = readListBegin()
readListEnd()
etype, size = readSetBegin()
readSetEnd()
bool = readBool()
byte = readByte()
i16 = readI16()
i32 = readI32()
i64 = readI64()
double = readDouble()
string = readString()
Thrift Protocols are stream oriented by design. There is no need for any
explicit framing. For instance, it is not necessary to know the length of a
string or the number of items in a list before we start serializing them.
Thrift 协议设计上是面向流的。无需任何显式的帧结构。例如,在开始序列化字符串或列表中的项目之前,不需要知道字符串的长度或列表中项目的数量。
Here are some of the protocols available for majority of the Thrift-supported
languages:
这里是大多数 Thrift 支持语言可用的一些协议:
-
binary: Fairly simple binary encoding — the length and type of a field are encoded as bytes followed by the actual value of the field.
binary:相当简单的二进制编码——字段的长度和类型以字节形式编码,随后是字段的实际值。 -
compact: Described in THRIFT-110
compact:在 THRIFT-110 中描述 -
json: json:
Processor 处理器
A Processor encapsulates the ability to read data from input streams and write
to output streams. The input and output streams are represented by Protocol
objects. The Processor interface is extremely simple:
处理器封装了从输入流读取数据和写入输出流的能力。输入和输出流由协议对象表示。处理器接口非常简单:
interface TProcessor {
bool process(TProtocol in, TProtocol out) throws TException
}
Service-specific processor implementations are generated by the compiler. The
Processor essentially reads data from the wire (using the input protocol),
delegates processing to the handler (implemented by the user) and writes the
response over the wire (using the output protocol).
服务特定的处理器实现由编译器生成。处理器本质上是从网络读取数据(使用输入协议),将处理委托给处理器(由用户实现),并通过网络写入响应(使用输出协议)。
Server 服务器
A Server pulls together all of the various features described above:
服务器将上述各种功能整合在一起:
-
Create a transport 创建运输
-
Create input/output protocols for the transport
为传输创建输入/输出协议 -
Create a processor based on the input/output protocols
基于输入/输出协议创建处理器 -
Wait for incoming connections and hand them off to the processor
等待传入连接并将其交给处理器
Next we discuss the generated code for specific languages. Unless mentioned
otherwise, the sections below will assume the following Thrift specification:
接下来我们讨论针对特定语言生成的代码。除非另有说明,以下各节将假设以下 Thrift 规范:
namespace cpp thrift.example
namespace java thrift.example
enum TweetType {
TWEET,
RETWEET = 2,
DM = 0xa,
REPLY
}
struct Location {
1: required double latitude;
2: required double longitude;
}
struct Tweet {
1: required i32 userId;
2: required string userName;
3: required string text;
4: optional Location loc;
5: optional TweetType tweetType = TweetType.TWEET;
16: optional string language = "english";
}
typedef list<Tweet> TweetList
struct TweetSearchResult {
1: TweetList tweets;
}
exception TwitterUnavailable {
1: string message;
}
const i32 MAX_RESULTS = 100;
service Twitter {
void ping(),
bool postTweet(1:Tweet tweet) throws (1:TwitterUnavailable unavailable),
TweetSearchResult searchTweets(1:string query);
oneway void zip()
}
Java
Generated Files 生成的文件
-
a single file (Constants.java) containing all constant definitions
一个包含所有常量定义的单个文件(Constants.java) -
one file per struct, enum and service
每个结构体、枚举和服务一个文件
$ tree gen-java `-- thrift `-- example |-- Constants.java |-- Location.java |-- Tweet.java |-- TweetSearchResult.java |-- TweetType.java `-- Twitter.java
|
Naming Conventions 命名规范
While the Thrift compiler does not enforce any naming conventions, it is
advisable to stick to standard naming conventions otherwise you may be in for
some surprises. For instance, if you have a struct named tweetSearchResults
(note the mixedCase), the Thrift compiler will generated a Java file named
TweetSearchResults (note the CamelCase) containing a class named
tweetSearchResults (like the original struct). This will obviously not
compile under Java. |
Types 类型
Thrift maps the various base and container types to Java types as follows:
Thrift 将各种基本类型和容器类型映射到 Java 类型如下:
-
bool: boolean
-
binary: byte[]
-
byte: byte 字节:byte
-
i16: short i16:短整数
-
i32: int
-
i64: long i64:长整型
-
double: double double:双精度浮点型
-
string: String string:字符串
-
list<t1>: List<t1>
-
set<t1>: Set<t1> set
: 集合 -
map<t1,t2>: Map<t1, t2> map
: 映射
As you can see, the mapping is straight forward and one-to-one for the most
part. This is not surprising given that Java was the primary target language
when the Thrift project began.
正如你所见,映射大多是直接且一一对应的。这并不令人惊讶,因为 Java 是 Thrift 项目开始时的主要目标语言。
Typedefs 类型定义
The Java language does not have any native support for "typedefs". So when the
Thrit Java code generator encounters a typedef declaration, it merely
substitutes it with the original type. That is, even though you may have
typedefd TypeA to TypeB, in the generated Java code, all references to
TypeB will be replaced by TypeA.
Java 语言本身不支持“typedef”。因此,当 Thrift 的 Java 代码生成器遇到 typedef 声明时,它只是用原始类型替换它。也就是说,即使你将 TypeA 定义为 TypeB,在生成的 Java 代码中,所有对 TypeB 的引用都会被替换为 TypeA。
Consider the example IDL above. The declaration for tweets in the generated
code for TweetSearchResults is simply public List<Tweets> tweets.
考虑上述示例 IDL。TweetSearchResults 生成代码中 tweets 的声明仅为 public List tweets。
Enums 枚举
Thrift enums map to Java enum types. You can obtain the numeric value of an
enum by using the getValue method (via the interface TEnum). In addition,
the compiler generates a findByValue method to obtain the enum corresponding
to a numeric value. This is more robust than using the ordinal feature of Java
enums.
Thrift 枚举映射到 Java 枚举类型。您可以通过使用 getValue 方法(通过接口 TEnum)获取枚举的数值。此外,编译器生成了一个 findByValue 方法,用于根据数值获取对应的枚举。这比使用 Java 枚举的 ordinal 特性更健壮。
Constants 常量
Thrift puts all defined constants in a public class named Constants as public
static final members. Constants of any of the primitive types are supported.
Thrift 将所有定义的常量放在一个名为 Constants 的公共类中,作为公共静态最终成员。支持任何原始类型的常量。
|
Contain your Constants 包含你的常量
If you have multiple Thrift files (in the same namespace) containing const
definitions, the Thrift compiler will overwrite the Constants.java file with
the definitions found in the file processed last. You must either define all
your constants in a single file, or invoke the compiler on a single file that
includes all the other files. |
C++
Generated Files 生成的文件
-
all constants go into a single .cpp/.h pair
所有常量都放入一个单独的 .cpp/.h 文件对中 -
all type definitions (enums and structs) go into another .cpp/.h pair
所有类型定义(枚举和结构体)都放入另一个 .cpp/.h 文件对中 -
each service gets its own .cpp/.h pair
每个服务都有自己独立的 .cpp/.h 文件对
$ tree gen-cpp |-- example_constants.cpp |-- example_constants.h |-- example_types.cpp |-- example_types.h |-- Twitter.cpp |-- Twitter.h `-- Twitter_server.skeleton.cpp
Types 类型
Thrift maps the various base and container types to C++ types as follows:
Thrift 将各种基本类型和容器类型映射到 C++ 类型如下:
-
bool: bool
-
binary: std::string
-
byte: int8_t
-
i16: int16_t
-
i32: int32_t i32: int32_t(32 位整数)
-
i64: int64_t i64: int64_t(64 位整数)
-
double: double double:双精度浮点型
-
string: std::string string: std::string(字符串)
-
list<t1>: std::vector<t1>
list: std::vector (列表) -
set<t1>: std::set<t1>
-
map<t1,t2>: std::map<T1, T2>
Other Languages 其他语言
Python, Ruby, Javascript etc.
Python,Ruby,Javascript 等。
Best Practices 最佳实践
Versioning/Compatibility
版本控制/兼容性
Protocols evolve over time. If an existing message type no longer meets all
your needs — for example, you’d like the message format to have an extra field — but you’d still like to use code created with the old format, don’t worry!
It’s very simple to update message types without breaking any of your existing
code. Just remember the following rules:
协议会随着时间演变。如果现有的消息类型不再满足您的所有需求——例如,您希望消息格式增加一个额外的字段——但您仍想使用基于旧格式创建的代码,不用担心!更新消息类型而不破坏现有代码非常简单。只需记住以下规则:
-
Don’t change the numeric tags for any existing fields.
不要更改任何现有字段的数字标签。 -
Any new fields that you add should be optional. This means that any messages serialized by code using your "old" message format can be parsed by your new generated code, as they won’t be missing any required elements. You should set up sensible default values for these elements so that new code can properly interact with messages generated by old code. Similarly, messages created by your new code can be parsed by your old code: old binaries simply ignore the new field when parsing. However, the unknown fields are not discarded, and if the message is later serialized, the unknown fields are serialized along with it — so if the message is passed on to new code, the new fields are still available.
您添加的任何新字段都应为可选的。这意味着使用“旧”消息格式的代码序列化的任何消息都可以被您新生成的代码解析,因为它们不会缺少任何必需的元素。您应为这些元素设置合理的默认值,以便新代码能够正确处理由旧代码生成的消息。同样,由新代码创建的消息也可以被旧代码解析:旧的二进制文件在解析时会简单地忽略新字段。然而,未知字段不会被丢弃,如果消息随后被序列化,未知字段也会随之序列化——因此如果消息传递给新代码,新字段仍然可用。 -
Non-required fields can be removed, as long as the tag number is not used again in your updated message type (it may be better to rename the field instead, perhaps adding the prefix "OBSOLETE_", so that future users of your .thrift can’t accidentally reuse the number).
非必填字段可以删除,只要标签编号在您更新后的消息类型中不再使用(可能更好的做法是重命名该字段,例如添加前缀“OBSOLETE_”,以防止未来使用您的 .thrift 文件的用户意外重复使用该编号)。 -
Changing a default value is generally OK, as long as you remember that default values are never sent over the wire. Thus, if a program receives a message in which a particular field isn’t set, the program will see the default value as it was defined in that program’s version of the protocol. It will NOT see the default value that was defined in the sender’s code.
更改默认值通常是可以的,只要你记住默认值从不通过网络传输。因此,如果程序接收到一条消息,其中某个特定字段未设置,程序将看到该字段在该程序版本协议中定义的默认值。它不会看到发送方代码中定义的默认值。
Resources 资源
Translations 翻译
-
Serbo-Croatian by Anja Skarba of http://webhostinggeeks.com/
塞尔维亚-克罗地亚语,由 http://webhostinggeeks.com/ 的 Anja Skarba 翻译