Thrift IDL 快速入门

栏目: 服务器 · 发布时间: 6年前

内容简介:众所周知,因为后端已经有一套服务注册和暴露机制,所以服务已经是RPC的形式,所以我们仅需要使用我们现在有一个

众所周知, Thrift 是一个RPC的框架,其可用于不同语言之间的服务相互调用。比如最近接触到的一个运用环境: *前端使用Node.Js重构了部分我们的老旧代码(前后端未分离的SpringBoot项目),我们后端使用zookeeper+Thrift为新的Node.Js前端项目提供基本的DAO层服务支持* 所以基于这个项目,我大概了解了一下Thrift,该文章则均以 Java 为基础语言。

II.如何入门

因为后端已经有一套服务注册和暴露机制,所以服务已经是RPC的形式,所以我们仅需要使用 Thrift IDL 来重写一遍我们需要暴露的方法即可, Thrift IDL 有两个比较好的参考选择:

  • Thrift 类型说明 可以参考官方文档:Thrift Type,简单来说, thrift 基本支持所有的 Java 基本类型以及引用类型:bool(boolean)、byte(byte)、i16(short)、i32(int)、i64(long)、double(double)、string(String)、binary(byte[])以及一些常用容器和自建类型(Struct);
  • Thrift IDL 的书写规范则可以参考 Thrift: The Missing Guide ,这个文档相较于官方文档有更多的例子可以参考。

III.TIPS

  • 很多参考和学习文档,都将 servicesstruct 放在一个 .thrift 文件中,这种方式将 service 和其所需的 struct 绑定在一起,会导致个别 struct 重复出现在多个 .thrift 文件中,导致大量的代码重复。所以, 应该与Java的编码风格保持一致,采用 POJO类(struct) + 接口(services) 的方案,利用 include 关键字,将struct引进services中使用
  • Thrift支持基本所有的 Java基本类型 ,但是注意是 基本类型 ,类似于Java中的Integer、Boolean、Long、Double等 基本类型包装类 是不支持的,或许你可以使用 struct 实现一个类似的包装类结构进行数据承载。
  • Thrift支持 enum 枚举类型,但是如果没有 description 的枚举类型也可以直接使用 string 来承接。
  • Thrift是通过序列化和反序列化来获取对应 struct 结构体的数据的,所以 struct 中的数据顺序一定要和 java 文件中的一致,否则可能会出现数据对应关系错乱或者数据丢失。
  • 在编写 struct 体时,要注意 java对象父级 ,如果父级中含有变量,不要忘记其变量的书写,且顺序一定在前面。
  • 如非必要, java对象 中的常量可以不出现在 thrift idlstruct 结构体中。
  • 时间 Date 我们固定使用 timestamp 时间戳的形式传递,即 long 型。

IV. 例子

我们现在有一个 Account 对象,需要将其变为 thrift 文件, Account 的结构如下:

public class Account extends BaseEntity implements SecurityUser{

		private static final long serialVersionUID = 1L;
		public static final String PASSWORD_TIME = "passwordTime";
	
		private String password;							// 密码
		private Date createTime;							// 创建时间
		private Date lastLoginTime;							// 最后登录时间
		private int loginCount = 0;							// 登录次数
		private boolean enabled = true;
		private Date passwordTime;							//密码修改时间
		private boolean freeze;								//账户是否被冻结
	
		//该账户的绑定信息,非持久化字段
		@Transient
		private Set<Binding> bindings = new HashSet();
	
		@Transient
		private String name;//保存登录时用的用户名,非持久化字段

		//省略getter和setter
  }
复制代码

根据上述结构我们可以书写如下的 Account.thrift :

/**
  * 账户信息
  */
struct Account{
	1: string password,	   //密码
	2: i64 createTime,     //创建时间
	3: i64 lastLoginTime,  //最后登录时间
	4: i32 loginCount,     //登陆次数
	5: bool enabled=true,
	6: i64 passwordTime,   //密码修改时间
	7: bool freeze,        //账户是否被冻结
}  
复制代码

但是经过测试前端调用接口获取到的 Account 信息,要么数据错位,要么数据丢失,问题出在哪里呢?这时,我们发现 Account 对象继承了 BaseEntity ,实现了 SecurityUser ,我们去查看一下继承的 BaseEntity 对象:

public abstract class BaseEntity extends IdEntity implements Cacheable, TypeAliases{
	
	private static final long serialVersionUID = 1L;
	
	private static final String CACHE_NAMESPACE = "entity" ;

	public BaseEntity() {
		super();
	}

	public BaseEntity(Long id) {
		super(id);
	}
	
	//省略下方代码
}
复制代码

我们发现其中并没有非常量变量,但是 BaseEntity 又继承了 IdEntity ,所以我们得再去看一看 IdEntity :

public abstract class IdEntity implements Serializable{

	private static final long serialVersionUID = -1L;

	/**
	 * Hibernate JPA环境中使用@GenericGenerator注解生成主键
	 */
	@Id
	@GeneratedValue(generator = "longIdGenerator")
	@GenericGenerator(name = "longIdGenerator", strategy = "net.qiyuesuo.framework.id.LongIdGenerator")
	protected Long id;
	
	public IdEntity() {
		super();
	}
	
	public IdEntity(Long id) {
		super();
		this.id = id;
	}

	//省略getter和setter
}
复制代码

这时我们发现 IdEntity 中含有一个 Id 的变量,所以我们需要重构一下刚刚书写的 Account.thrift

/**
  * 账户信息
  */
struct Account{
	1: i64 id,			//账户Id
	2: string password,	 //密码
	3: i64 createTime,  //创建时间
	4: i64 lastLoginTime, //最后登录时间
	5: i32 loginCount, //登陆次数
	6: bool enabled,
	7: i64 passwordTime,  //密码修改时间
	8: bool freeze, //账户是否被冻结
}  
复制代码

书写完 Account.thrift 后,我们需要写其相应的接口即 service ,查看 Interface AccountService :

public interface AccountService {
	
	/**
	 * 创建账户
	 * @param account
	 * @return 返回创建后的Account对象
	 */
	Account create(Account account);
	
	/**
	 * 更新账户信息
	 * @param account
	 * @return
	 */
	boolean update(Account account);
	
	/**
	 * 修改开放平台密码  传入的 密码是未加密的
	 * @param username
	 * @param newPassword
	 * @return
	 */
	boolean updatePasswd(String username, String newPassword);
	
	/**
	 * 重置密码
	 * @param username 用户名
	 * @param newPassword 新密码
	 */
	void resetPasswd(String username, String newPassword);

	/**
	 * 验证用户名和密码是否匹配
	 * @param username
 	* @param password
	 */
	boolean matches(String username,String password);
}
复制代码

有很多方法,但是 如果前端只需要用到校验用户名和密码的方法 ,那么我就只需要暴露创建账户的方法,即:

include "Account.thrift"

service AccountService{
	/*
	 * 校验用户名和密码
	 */
	bool matches(1: string username,2: string password),
}
复制代码

这样我们就完成了一个关于用户名和密码的校验方法的 thrift idl 文档的书写,前端需要执行 thrift 的一条语句对文件进行编译,以 node.js 为例(具体可参考: Apache Thrift Tutorial

thrift --gen <language> <Thrift filename>

thrift -r --gen js:node Account.thrift
thrift -r --gen js:node AccountService.thrift复制代码

以上所述就是小编给大家介绍的《Thrift IDL 快速入门》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Haskell函数式编程基础

Haskell函数式编程基础

Simon Thompson / 科学出版社 / 2013-7-1 / 129.00

《Haskell函数式编程基础(第3版)》是一本非常优秀的Haskell函数式程序设计的入门书,各章依次介绍函数式程序设计的基本概念、编译器和解释器、函数的各种定义方式、简单程序的构造、多态和高阶函数、诸如数组和列表的结构化数据、列表上的原始递归和推理、输入输出的控制处理、类型分类与检测方法、代数数据类型、抽象数据类型、惰性计算等内容。书中包含大量的实例和习题,注重程序测试、程序证明和问题求解,易......一起来看看 《Haskell函数式编程基础》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器