Thrift IDL 快速入門

I.背景

衆所周知,Thrift是一個RPC的框架,其可用於不一樣語言之間的服務相互調用。好比最近接觸到的一個運用環境: *前端使用Node.Js重構了部分咱們的老舊代碼(先後端未分離的SpringBoot項目),咱們後端使用zookeeper+Thrift爲新的Node.Js前端項目提供基本的DAO層服務支持* 因此基於這個項目,我大概瞭解了一下Thrift,該文章則均以Java爲基礎語言。前端


II.如何入門

由於後端已經有一套服務註冊和暴露機制,因此服務已是RPC的形式,因此咱們僅須要使用Thrift IDL來重寫一遍咱們須要暴露的方法便可,Thrift IDL有兩個比較好的參考選擇:java

  • 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的結構以下:node

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:apache

/**
  * 帳戶信息
  */
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.thriftide

/**
  * 帳戶信息
  */
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 Tutorialui

thrift --gen <language> <Thrift filename>

thrift -r --gen js:node Account.thrift
thrift -r --gen js:node AccountService.thrift複製代碼
相關文章
相關標籤/搜索