Kubernetes官方java客户端之二:序列化和反序列化问题

简介: K8S官方java客户端在使用中会遇到json处理问题,在此说明

欢迎访问我的GitHub

https://github.com/zq2599/blog_demos

问题场景

本文是《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方法命中了该逻辑,如果您尝试用在红框处打上断点观察,会发现有很多方法都符合此条件:
    在这里插入图片描述

    解决问题的思路

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

  3. 让Jackson在序列化的时候,能够调用正确的方法,以IntOrString为例,如果此时内部保存int型数据,就应该执行其getIntValue方法即可;

  4. 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程序员精心准备的工具;

欢迎关注阿里云开发者社区:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
5天前
|
JSON NoSQL Java
Redis入门到通关之Java客户端SpringDataRedis(RedisTemplate)
Redis入门到通关之Java客户端SpringDataRedis(RedisTemplate)
18 0
|
2月前
|
存储 Java 数据库
|
1天前
|
Java
JavaFX库用于在Java中绘制K线图,适合构建富客户端应用。
JavaFX库用于在Java中绘制K线图,适合构建富客户端应用。以下是一个简单的K线图绘制示例:创建OHLCChart,设置标题和坐标轴,创建数据集并添加数据点,最后显示在Scene中。要定制图表外观,可利用JavaFX的丰富参数和方法。查阅JavaFX文档以获取更多细节。
10 3
|
4天前
|
存储 Java 测试技术
滚雪球学Java(22):序列化和反序列化
【4月更文挑战第11天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
19 1
滚雪球学Java(22):序列化和反序列化
|
7天前
|
SQL 存储 安全
每日一道面试题:Java中序列化与反序列化
每日一道面试题:Java中序列化与反序列化
8 0
|
11天前
|
Java API Apache
ZooKeeper【基础 03】Java 客户端 Apache Curator 基础 API 使用举例(含源代码)
【4月更文挑战第11天】ZooKeeper【基础 03】Java 客户端 Apache Curator 基础 API 使用举例(含源代码)
25 11
|
18天前
|
存储 Java
Java输入输出:解释一下序列化和反序列化。
Java中的序列化和反序列化是将对象转换为字节流和反之的过程。ObjectOutputStream用于序列化,ObjectInputStream则用于反序列化。示例展示了如何创建一个实现Serializable接口的Person类,并将其序列化到文件,然后从文件反序列化回Person对象。
26 5
|
22天前
|
存储 Java Maven
java序列化
java序列化
|
2月前
|
监控 Java 网络安全
|
2月前
|
存储 C#
C#中的序列化和反序列化
C#中的序列化和反序列化
12 0

推荐镜像

更多