Skip to content

migrate hsf 2 springcloud serialization

liubao edited this page Jun 1, 2022 · 1 revision

背景信息

HSF和Dubbo的早期版本采用 hessian2 进行编码。 hessian2 是一种跨语言的二进制编码协议, HSF和Dubbo基于这个协议进行了自定义, 开发了 hessian-lite 实现。 hessian-lite 的实现不是跨语言的, 能够支持非常复杂 JAVA 场景的序列化,包括泛型、抽象类等。

将HSF和Dubbo的RPC修改为Spring Cloud(参考方案), 会存在很多序列化问题。下面列举一些常见场景及其解决方案。 这些问题,很多都和业务代码的特殊用法有关,在Spring Cloud场景下,需要有不同的写法。

为了描述方便,下面用hessian和jackson分别代表两种框架的序列化方式。

问题列表

Map<String, Object> 序列化

Map<String, Object> model = new HashMap<>();
model.put("key1", (byte)1);
model.put("key2", 1);

Map类型在hessian和jackson都能序列化。hessian反序列化能够得到value的原始类型,但是jackson则不一定。 比如上面的代码, hessian能够得到key1为byte, key2为integer,但是jackson得到的都是integer。

接口定义为基类,但是需要得到子类信息

class Base {}
class Child extends Base {}

public Base echo(Base b) { if (b instanceof Child) {} }

jackson在反序列化以后,只能得到基类信息,子类信息和类型都丢失了。 如果需要得到子类信息,需要在基类和子类增加相应的标签:

@JsonTypeInfo(use = Id.CLASS, defaultImpl = Base.class)
class Base {}
@JsonTypeInfo(use = Id.CLASS, defaultImpl = Child.class)
class Child extends Base {}

更多基类、泛型的例子参考

属性使用泛型

class Generic<T> {T data}

泛型序列化, jackson不会包含data的类型信息。这个问题和基类序列化问题类似。 如果基类增加了@JsonTypeInfo, 泛型的属性也需要增加这个信息,否则会导致反序列化失败。

class Generic<T> {
@JsonTypeInfo(use = Id.CLASS
T data;
}

更多基类、泛型的例子参考

特殊序列化要求

如果存在微服务A、B、C, A是jackson应用,B、C是hessian应用, A调用B、B调用C, 有些业务需要在A定制ObjectMapper,将日期序列化为类似yyyy-MM-dd的格式。 将B、C都改造为jackson应用后,在会导致B调用C的时候,B序列化日期类型为yyyy-MM-dd的格式, C无法反序列化。 这种情况,建议统一日期的格式为ISO标准格式,前后台都遵循这个标准解析。

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss Z", timezone="America/New_York")
Date time

兼容性方案

Spring Cloud Huawei 1.7.1-2020.0.x 版本提供了兼容性方案,可以采用hessian2编码。 例子如下:

  @PostMapping(path = "base", consumes = "x-application/hessian2",
      produces = "x-application/hessian2")
  Base base(@RequestBody Base b);

完整例子参考

Clone this wiki locally