1. 程式人生 > >Kubernetes官方java客戶端之二:序列化和反序列化問題

Kubernetes官方java客戶端之二:序列化和反序列化問題

### 歡迎訪問我的GitHub [https://github.com/zq2599/blog_demos](https://github.com/zq2599/blog_demos) 內容:所有原創文章分類彙總及配套原始碼,涉及Java、Docker、Kubernetes、DevOPS等; ### 問題場景 本文是《Kubernetes官方java客戶端》的第二篇,在進入編碼實戰章節之前,有個問題需要大家有足夠的瞭解,避免在後面的實戰中耗費精力處理此類問題,來看看究竟是什麼問題: 1. SpringBoot是常用的應用框架,《Kubernetes官方java客戶端》系列的應用都是基於SpringBoot-2.3.1版本的; 2. 下圖是SpringBoot-2.3.1.RELEASE的官方文件,紅框表明預設的JSON處理庫是Jackson: ![在這裡插入圖片描述](https://img2020.cnblogs.com/other/485422/202101/485422-20210104074816720-1669097882.png) 3. 看到這裡您是否有種不祥預感:K8S官方java客戶端是谷歌的,涉及到JSON處理時會不會首選自家的Gson? 4. V1HTTPGetAction.java是java客戶端中常用到的資料結構,用來封裝http請求相關的引數,來看看其原始碼,如下圖,果然用上了Gson的註解: ![在這裡插入圖片描述](https://img2020.cnblogs.com/other/485422/202101/485422-20210104074818382-947759646.png) 5. 上圖提到的IntOrString類要重點關注,用處廣泛,開啟其原始碼如下圖,請記下紅框2中的程式碼,後面提到的問題就來源於此: ![在這裡插入圖片描述](https://img2020.cnblogs.com/other/485422/202101/485422-20210104074819707-157803312.png) - 小結:SpringBoot預設的JSON處理類是Jackson,K8S官方java客戶端內的Bean在涉及到JSON相關的序列化和反序列化處理時,使用了Gson註解,因此上述Bean例項在SpringBoot中涉及到JSON處理時,可能會有問題(這時只能說可能),例如RestController返回物件,會被Jackson轉為JSON; ### 復現問題 1. 這裡用一個SpringBoot工程來演示此問題(該工程名為OutsideclusterApplication,下一篇文章會詳細說明),如下程式碼是個http介面響應,可見V1PodList例項作為介面返回時,會被SpringBoot用Jackson轉為JSON返回給前端: ```shell @RequestMapping(value = "/hello") public V1PodList hello() throws Exception { // 存放K8S的config檔案的全路徑 String kubeConfigPath = "/Users/zhaoqin/temp/202007/05/config"; // 以config作為入參建立的client物件,可以訪問到K8S的API Server ApiClient client = ClientBuilder .kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))) .build(); Configuration.setDefaultApiClient(client); CoreV1Api api = new CoreV1Api(); // 呼叫客戶端API取得所有pod資訊 V1PodList v1PodList = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null); return v1PodList; } ``` 2. 上述程式碼執行起來,在瀏覽器訪問該介面時,控制檯丟擲以下錯誤,IntOrString.getStrValue方法,就是前面咱們看過的那段,IntOrString中實際上儲存的是int資料,但是Jackson執行了其getStrValue方法: ![在這裡插入圖片描述](https://img2020.cnblogs.com/other/485422/202101/485422-20210104074821225-1443774302.png) 3. 至於為什麼Jackson會執行getStrValue方法,篇幅原因就不在此展開了,簡單提一下,在java客戶端的BeanPropertyWriter類中,選擇方法的邏輯如下圖,紅框中展示了判定邏輯,此處getStrValue方法命中了該邏輯,如果您嘗試用在紅框處打上斷點觀察,會發現有很多方法都符合此條件: ![在這裡插入圖片描述](https://img2020.cnblogs.com/other/485422/202101/485422-20210104074821962-585896793.png) ### 解決問題的思路 我這裡,解決問題的思路有兩個: 1. 讓Jackson在序列化的時候,能夠呼叫正確的方法,以IntOrString為例,如果此時內部儲存int型資料,就應該執行其getIntValue方法即可; 2. Bean中使用了Gson註釋,就是打算用Gson來處理序列化和反序列化操作的,因此序列化和反序列化的地方都改用Gson處理; - 上述兩個思路,我選擇了第二種,畢竟第一種太難了... ### 解決問題 1. 問題解決起來並不難,先看SpringBoot-2.3.1.RELEASE官方文件: ![在這裡插入圖片描述](https://img2020.cnblogs.com/other/485422/202101/485422-20210104074822663-837242560.png) 2. 結合官方文件,我們要做兩件事情: - 首先,classpath中有Gson,這個已經有了,因為K8S官方java客戶端會依賴Gson; - 其次,classpath中不要出現Jackson,為了達到這個目的我們需要做以下操作,排除spring-boot-starter-web的依賴(為什麼不直接排除jackson的庫呢?您可以執行mvn dependency:tree命令細看依賴樹,會發現對jackson的依賴並非單一關係): ```xml ``` 3. 建議您執行mvn dependency:tree命令細看整個專案的依賴樹,確保jackson依賴已經全部去掉; 4. 再次執行上述專案,如下圖,服務端不再報錯,頁面上返回資料正常: ![在這裡插入圖片描述](https://img2020.cnblogs.com/other/485422/202101/485422-20210104074823143-1547529755.png) ### 使用Jackson的場景 - 上述方式雖然可行,但並非所有專案都能堅持使用Gson而放棄Jackson,對於使用Jackson的專案,請避免Jackson參與K8S官方java客戶端bean的序列化和反序列化操作,以上面出現的Controller程式碼為例,不要直接將V1PodList例項返回,您可以選擇先用Gson序列化成JSON字串,再返回字串給前端,也可以自己定義VO物件,將V1PodList例項轉成VO物件再返回; - 至此,使用K8S官方java客戶端之前要注意的問題已經弄明白了,接下來的進入精彩的實戰章節吧,一起體驗kubernetes官方為java程式設計師精心準備的工具; ### 你不孤單,欣宸原創一路相伴 1. [Java系列](https://xinchen.blog.csdn.net/article/details/105068742) 2. [Spring系列](https://xinchen.blog.csdn.net/article/details/105086498) 3. [Docker系列](https://xinchen.blog.csdn.net/article/details/105086732) 4. [kubernetes系列](https://xinchen.blog.csdn.net/article/details/105086794) 5. [資料庫+中介軟體系列](https://xinchen.blog.csdn.net/article/details/105086850) 6. [DevOps系列](https://xinchen.blog.csdn.net/article/details/105086920) ### 歡迎關注公眾號:程式設計師欣宸 > 微信搜尋「程式設計師欣宸」,我是欣宸,期待與您一同暢遊Java世界... [https://github.com/zq2599/blog_demos](https://github.com/zq2599/blo