上一篇 介绍过Thrift的类型,那这一篇来说说Thrift的IDL接口文件(The Thrift interface definition language)的结构。Thrift IDL文件由Thrift代码生成工具处理,生成各种目标语言的代码,以支持IDL文件中定义的结构和服务实现跨语言服务调用。
0、Comments - 注释
Thrift支持shell风格、C/C++/Java风格的注释。示例:
# shell风格注释.
/*
* 多行注释
* 类似C/C++/Java
*/
// C++/Java 当行注释
1、Description - 描述
Thrift文件的描述跟一般语言一样在文件顶部通过注释来表述服务的内容等等信息
2、Document - 文档
Thrift文档部分包括0个或者多个Header部分和Definition部分,下面先说Header部分
- Header - 头部分
Header部分包括Thrift include、C++ include和namespace定义
- Thrift Include:将所有声明包含的Thrift文档都包含到当前Thrift中来,语法:
inlucde "文件名"
//示例
inlucde "other.thrift"
- C++ Include:将用户自己的C++头文件包含到当前Thrift中来,语法:
cpp_include "头文件"
//示例
cpp_include "string"
- Namespace:定义名称空间/包名/模块等等,可以使用编程语言名称规定某一特定语言的namespace,用*表示所有未匹配到的语言的namespace,语法:
namespace [语言名称] 标识符
//示例
namespace java thrift.test
namespace php ThriftTest
namespace cpp thrift.test
namespace * thrifttest
- Definition - 定义部分
定义部分包括 Const 、 Typedef 、 Enum 、 Senum 、 Struct 、 Union 、 Exception 、 Service
- Const:定义常量,Thrift允许使用JSON来定义复杂类型和struct类型,语法:
const 字段类型 名称标识 = 值 | 列表
//示例
const i32 INT_CONST = 1234
const map<string,string> MAP_CONST = {"test":"hello world"}
- Typedef:Thrift 支持C/C++风格的类型自定义,语法:
typedef 原类型 自定义类型
typedef i32 MyInteger
- Enum:Thrift枚举类型只支持单个32位int类型数据,第一个元素如果没有给值那么默认是0,之后的元素如果没有给值,则是在前一个元素基础上加1,语法:
enum 名称标识 {
字段标识 = int常量
}
//示例
enum Numberz
{
ONE = 1,
TWO, //值是2,前一个元素加1
THREE, //值是3
FIVE = 5,
SIX,
EIGHT = 8
}
- Struct:这个在前一篇文章中有介绍, 类似于C的struct,是一系列相关数据的封装,在OOP语言中会转换为类(class),struct的每个元素包括一个唯一的数字标识、一个数据类型、一个名称和一个可选的默认值。语法:
struct 名称标识 {
数字标识: (required|optional)? 类型 名称标识 (= 值)?
}
//示例
struct Xtruct{
1: string string_thing,
4: required i8 byte_thing,
16: optional string optional_thing = "default value"
}
关于字段的必选和可选的说明:
required:
1、写:必须字段始终写入,并且应该设置这些字段。
2、读:必须字段始终读取,并且它们将包含在输入流中
3、默认值:始终写入
注意:如果一个必须字段在读的时候丢失,则会抛出异常或返回错误,所以在版本控制的时候,要严格控制字段的必选和可选,必须字段如果被删或者改为可选,那将会造成版本不兼容。
optional:
1、写:可选字段仅在设置时写入
2、读:可选字段可能是也可能不是输入流的一部分
3、默认值:在设置了isset标志时写入
Thrift使用所谓的“isset”标志来指示是否设置了特定的可选字段, 仅设置了此标志的字段会写入,相反,仅在从输入流中读取字段值时才设置该标志。
default:
1、写:理论上总是写入,但是有一些特例
2、读:跟optional一样
3、默认值:可能不会写入
默认类型是required和optional的结合,可选输入(读),必须输出(写)。
- Union:类似于C++的union,成员默认全部是optional类型,语法
union 名称标识 {
数字标识: (required|optional)? 类型 名称标识 (= 值)?
}
//示例
union SomeUnion {
2: string string_thing,
3: i32 i32_thing
}
- Exception:异常跟struct类似,会跟目标语言本地异常集成,语法:
exception 名称标识 {
数字标识: (required|optional)? 类型 名称标识 (= 值)?
}
//示例
exception Xception {
1: i32 errorCode,
2: string message
}
- Service:service是Thrift 服务器提供的一系列功能列表接口,在客户端就是调用这些接口来完成操作,语法:
service 名称标识 (extends 名称标识)? {
Function*
}
其中Function语法为:
oneway? 返回类型 名称标识(字段列表) throws(字段列表)?
//示例
service ThriftTest {
void testVoid(),
bool testBool(1: bool thing),
map<i32,i32> testMap(1: map<i32,i32> thing),
Xtruct testStruct(1: Xtruct thing),
list<i32> testList(1: list<i32> thing),
void testException(1: string arg) throws(1: Xception err1),
oneway void testOneway(1:i32 secondsToSleep)
}
最后来一个官方示例:
/*
* 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.
*/
/**
* fb303.thrift
*/
namespace java com.facebook.fb303
namespace cpp facebook.fb303
namespace perl Facebook.FB303
namespace netcore Facebook.FB303.Test
/**
* Common status reporting mechanism across all services
*/
enum fb_status {
DEAD = 0,
STARTING = 1,
ALIVE = 2,
STOPPING = 3,
STOPPED = 4,
WARNING = 5,
}
/**
* Standard base service
*/
service FacebookService {
/**
* Returns a descriptive name of the service
*/
string getName(),
/**
* Returns the version of the service
*/
string getVersion(),
/**
* Gets the status of this service
*/
fb_status getStatus(),
/**
* User friendly description of status, such as why the service is in
* the dead or warning state, or what is being started or stopped.
*/
string getStatusDetails(),
/**
* Gets the counters for this service
*/
map<string, i64> getCounters(),
/**
* Gets the value of a single counter
*/
i64 getCounter(1: string key),
/**
* Sets an option
*/
void setOption(1: string key, 2: string value),
/**
* Gets an option
*/
string getOption(1: string key),
/**
* Gets all options
*/
map<string, string> getOptions(),
/**
* Returns a CPU profile over the given time interval (client and server
* must agree on the profile format).
*/
string getCpuProfile(1: i32 profileDurationInSec),
/**
* Returns the unix time that the server has been running since
*/
i64 aliveSince(),
/**
* Tell the server to reload its configuration, reopen log files, etc
*/
oneway void reinitialize(),
/**
* Suggest a shutdown to the server
*/
oneway void shutdown(),
}
3、生成目标语言代码
下载官方代码生成工具,windows下载地址https://mirrors.tuna.tsinghua.edu.cn/apache/thrift/,其他平台下载官方源码包编译即可。
生成代码使用命令:
thrift --gen <language> <Thrift filename>
如果有thrift文件中有包含其他thrift,可以使用递归生成命令:
thrift -r --gen <language> <Thrift filename>