http://anruence.com/2018/06/27/enum-thrift/
問題
在用注解定義的Thrift enum 中,如果客戶端端和服務端的enum定義不同,比如調換了enum中的枚舉值的順序,就會發生調用端發送的枚舉參數與服務端解析得到的枚舉參數不一致的問題。
猜想
java 中的enum類的每一個具體的枚舉值都有一個ordinal,代表其聲明順序,從零開始。thrift在序列化和反序列化時會將枚舉值轉換為一個整數傳遞,所以枚舉值的具體含義與調用端和服務端各自的enum代碼中聲明順序有關。
Thrift 注解的實現中對於thrift中每個關鍵字都有對應的編解碼器,enum對應的為EnumThriftCodec<T extends Enum,這個類繼承了接口ThriftCodec 。具體代碼如下:
1 |
package com.facebook.swift.codec.internal; |
初步結論
現在總結一下,Thrift 注解方式會將枚舉值編碼成一個int進行網絡傳輸,而在處理具體的枚舉值與整數之間的對應關系的時候有兩種策略:
如果枚舉類顯式聲明了枚舉值與整數之間的對應關系,則根據聲明的規則進行編解碼
如果枚舉類中沒有顯式聲明對應關系,則根據聲明順序的索引進行編解碼。
具備了以上知識,就能解答文章最開始的問題了:如果客戶端和服務端的枚舉類里沒有顯式聲明枚舉值和整數值的對應關系,那么在編解碼的時候的對應關系就是枚舉值的聲明順序,如果兩端的枚舉類中枚舉值的順序不一致,就會導致兩端編解碼的的枚舉值不一致。
深入探究
接下來再進一步探索,EnumThriftCodec如何判斷一個枚舉類是否聲明了枚舉值到整數的對應關系?為了回答這個問題,需要首先弄清楚EnumThriftCodec中的成員變量EnumMetadata的具體內容:
ThriftEnumMetadata.java
1 |
/* |