内容简介:众所周知,因为后端已经有一套服务注册和暴露机制,所以服务已经是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
-
很多参考和学习文档,都将
services
和struct
放在一个.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 idl
的struct
结构体中。 -
时间
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 快速入门》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- TiDB入门(四):从入门到“跑路”
- MyBatis从入门到精通(一):MyBatis入门
- MyBatis从入门到精通(一):MyBatis入门
- Docker入门(一)用hello world入门docker
- 赵童鞋带你入门PHP(六) ThinkPHP框架入门
- 初学者入门 Golang 的学习型项目,go入门项目
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Haskell函数式编程基础
Simon Thompson / 科学出版社 / 2013-7-1 / 129.00
《Haskell函数式编程基础(第3版)》是一本非常优秀的Haskell函数式程序设计的入门书,各章依次介绍函数式程序设计的基本概念、编译器和解释器、函数的各种定义方式、简单程序的构造、多态和高阶函数、诸如数组和列表的结构化数据、列表上的原始递归和推理、输入输出的控制处理、类型分类与检测方法、代数数据类型、抽象数据类型、惰性计算等内容。书中包含大量的实例和习题,注重程序测试、程序证明和问题求解,易......一起来看看 《Haskell函数式编程基础》 这本书的介绍吧!