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 快速入门》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

Building Social Web Applications

Building Social Web Applications

Gavin Bell / O'Reilly Media / 2009-10-1 / USD 34.99

Building a social web application that attracts and retains regular visitors, and gets them to interact, isn't easy to do. This book walks you through the tough questions you'll face if you're to crea......一起来看看 《Building Social Web Applications》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具