欢迎访问我的GitHub

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:

  3. 看到这里您是否有种不祥预感:K8S官方java客户端是谷歌的,涉及到JSON处理时会不会首选自家的Gson?

  4. V1HTTPGetAction.java是java客户端中常用到的数据结构,用来封装http请求相关的参数,来看看其源码,如下图,果然用上了Gson的注解:

  5. 上图提到的IntOrString类要重点关注,用处广泛,打开其源码如下图,请记下红框2中的代码,后面提到的问题就来源于此:

  • 小结:SpringBoot默认的JSON处理类是Jackson,K8S官方java客户端内的Bean在涉及到JSON相关的序列化和反序列化处理时,使用了Gson注解,因此上述Bean实例在SpringBoot中涉及到JSON处理时,可能会有问题(这时只能说可能),例如RestController返回对象,会被Jackson转为JSON;

复现问题

  1. 这里用一个SpringBoot工程来演示此问题(该工程名为OutsideclusterApplication,下一篇文章会详细说明),如下代码是个http接口响应,可见V1PodList实例作为接口返回时,会被SpringBoot用Jackson转为JSON返回给前端:
@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;
}
  1. 上述代码运行起来,在浏览器访问该接口时,控制台抛出以下错误,IntOrString.getStrValue方法,就是前面咱们看过的那段,IntOrString中实际上保存的是int数据,但是Jackson执行了其getStrValue方法:

  2. 至于为什么Jackson会执行getStrValue方法,篇幅原因就不在此展开了,简单提一下,在java客户端的BeanPropertyWriter类中,选择方法的逻辑如下图,红框中展示了判定逻辑,此处getStrValue方法命中了该逻辑,如果您尝试用在红框处打上断点观察,会发现有很多方法都符合此条件:

解决问题的思路

我这里,解决问题的思路有两个:

  1. 让Jackson在序列化的时候,能够调用正确的方法,以IntOrString为例,如果此时内部保存int型数据,就应该执行其getIntValue方法即可;
  2. Bean中使用了Gson注释,就是打算用Gson来处理序列化和反序列化操作的,因此序列化和反序列化的地方都改用Gson处理;
  • 上述两个思路,我选择了第二种,毕竟第一种太难了...

解决问题

  1. 问题解决起来并不难,先看SpringBoot-2.3.1.RELEASE官方文档:

  2. 结合官方文档,我们要做两件事情:

  • 首先,classpath中有Gson,这个已经有了,因为K8S官方java客户端会依赖Gson;
  • 其次,classpath中不要出现Jackson,为了达到这个目的我们需要做以下操作,排除spring-boot-starter-web的依赖(为什么不直接排除jackson的库呢?您可以执行mvn dependency:tree命令细看依赖树,会发现对jackson的依赖并非单一关系):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</exclusion>
</exclusions>
</dependency>
  1. 建议您执行mvn dependency:tree命令细看整个项目的依赖树,确保jackson依赖已经全部去掉;
  2. 再次运行上述项目,如下图,服务端不再报错,页面上返回数据正常:

使用Jackson的场景

  • 上述方式虽然可行,但并非所有项目都能坚持使用Gson而放弃Jackson,对于使用Jackson的项目,请避免Jackson参与K8S官方java客户端bean的序列化和反序列化操作,以上面出现的Controller代码为例,不要直接将V1PodList实例返回,您可以选择先用Gson序列化成JSON字符串,再返回字符串给前端,也可以自己定义VO对象,将V1PodList实例转成VO对象再返回;

  • 至此,使用K8S官方java客户端之前要注意的问题已经弄明白了,接下来的进入精彩的实战章节吧,一起体验kubernetes官方为java程序员精心准备的工具;

你不孤单,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

欢迎关注公众号:程序员欣宸

微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界...

https://github.com/zq2599/blog_demos

Kubernetes官方java客户端之二:序列化和反序列化问题的更多相关文章

  1. Kubernetes官方java客户端之三:外部应用

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  2. Kubernetes官方java客户端之四:内部应用

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  3. Kubernetes官方java客户端之八:fluent style

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  4. Kubernetes官方java客户端之五:proto基本操作

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  5. Kubernetes官方java客户端之六:OpenAPI基本操作

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. Kubernetes官方java客户端之一:准备

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  7. Kubernetes官方java客户端之七:patch操作

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  8. HBase的java客户端测试(二)---DML操作

    测试准备 [首先同步时间:] for node in CloudDeskTop master01 master02 slave01 slave02 slave03;do ssh $node " ...

  9. Java基础知识:序列化和反序列化

    一.序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存 ...

随机推荐

  1. 学习工具---maven

    写在前面 为什么要用maven? 作为一跨平台的项目管理工具,它有着以下丰富的应用场景: 作为程序员,有相当一部分时间花在编译.运行单元测试.生成文档.打包.部署和发布等不起眼的工作上,而maven将 ...

  2. PyQt(Python+Qt)学习随笔:Qt Designer中主窗口对象的animated属性

    animated属性用于设置在操作可浮动部件和工具栏时是否设置动画. 当一个可浮动部件或工具栏被拖到主窗口上时,主窗口将调整其内容,以显示浮动部件或工具栏应该放置的位置.设置此属性后主窗口将使用平滑动 ...

  3. Python追加文件内容

    测试中需要造几百个账号,写了个脚本可以自动生成账号,但想把生成的账号写入一个文件, 开始用的如下的write()方法,发下会先把原文件的内容清空再写入新的东西,文件里面每次都是最新生成的一个账号 mo ...

  4. C# 9.0新特性详解系列之五:记录(record)和with表达式

    1 背景与动机 传统面向对象编程的核心思想是一个对象有着唯一标识,表现为对象引用,封装着随时可变的属性状态,如果你改变了一个属性的状态,这个对象还是原来那个对象,就是对象引用没有因为状态的改变而改变, ...

  5. 题解 CF1375E Inversion SwapSort

    蒟蒻语 这题是真的奇妙... 想了好久才想明白. 蒟蒻解 考虑冒泡排序是怎样的. 对于相邻的两个数 \(a_i, a_{i+1}\),如果 \(a_i>a_{i+1}\) 那么就交换两个数. 总 ...

  6. Codeforces Edu Round 63 A-E

    A. Reverse a Substring 容易看出,只要符合递增顺序就符合\(NO\),否则则可以找到一组,每次记录最大值比较即可. #include <cstdio> #includ ...

  7. C++ 虚函数表与多态 —— 虚函数表的内存布局

       C++面试经常会被问的问题就是多态原理.如果对C++面向对象本质理解不是特别好,问到这里就会崩. 下面从基本到原理,详细说说多态的实现:虚函数 & 虚函数表.   1. 多态的本质: 形 ...

  8. USB接口禁用小工具v1.0.1

    由论坛用户原创制作的一个USB接口工具, 可选择手动/自动启动或者禁止启动模式, 开启禁止启动模式后USB接口将关闭识别功能, 有效防止U盘设备侵入,对于机房实验室设施来说相当管用. 下载地址:htt ...

  9. AWT04-AWT常用组件

    1.基本组件 方法名 说明 Button 按钮 Canvas 用于绘画的画布 Checkbox 复选框组件 CheckboxGroup 用于将多个Checkbox合成一组,一组Checkbox只有一个 ...

  10. Linux下MySQL数据库的备份与恢复

    Linux下MySQL数据库的备份与恢复 作者:Grey 原文地址: Github 语雀 博客园 基于版本 MySQL5.7 Deepin Linux 15.11 xtrabackup-2.4.18 ...