代码之家  ›  专栏  ›  技术社区  ›  Jonathan R

维特。x 4 eventbus使用相同的编解码器序列化多个类

  •  0
  • Jonathan R  · 技术社区  · 4 年前

    有没有办法为多个类注册一个编解码器?基本上,我所有的类都应该使用Jackson对象映射器序列化。但似乎我必须为每个类创建一个自定义编解码器(尽管我可以使用泛型对其进行一点抽象)。

    一个小代码示例:

    编解码器:

    class JacksonCodec<T>(private val mapper: ObjectMapper, private val clazz: Class<T>) : MessageCodec<T, T> {
        override fun encodeToWire(buffer: Buffer, s: T) {
            buffer.appendBytes(mapper.writeValueAsBytes(s))
        }
    
        override fun decodeFromWire(pos: Int, buffer: Buffer): T {
            val length = buffer.getInt(pos)
            val bytes = buffer.getBytes(pos + 4, pos + 4 + length)
            return mapper.readValue(bytes, clazz)
        }
        ...
    }
    

    为我要序列化的每个类注册编解码器:

    vertx.eventBus()
            .registerDefaultCodec(A::class.java, JacksonCodec(DatabindCodec.mapper(), A::class.java))
        vertx.eventBus()
    vertx.eventBus()
            .registerDefaultCodec(B::class.java, JacksonCodec(DatabindCodec.mapper(), B::class.java))
        vertx.eventBus()
    

    代码示例是kotlin,但同样适用于Java。

    0 回复  |  直到 4 年前
        1
  •  1
  •   Alexey Soshin    4 年前
        2
  •  0
  •   Tom    4 年前

    这是可能的,但也有一些局限性和怪癖。我不建议这样做。

    让我们从限制开始:

    1. 它不能在集群模式下使用
    2. 每次通过eventbus发送内容时,都必须声明编解码器名称。

    如果您创建了一个通用编解码器,用Jackson对类进行编码,每次通过eventbus发送内容时,请确保使用 codecName deliveryOptions ,您只能注册一次,并将其用于所有类。

    完整示例:

    fun main() {
      val vertx = Vertx.vertx()
      vertx.eventBus().registerCodec(GenericCodec())
    
      vertx.eventBus().consumer<Foo>("test-address") {
        println(it.body())
        it.reply(Bar(), genericDeliveryOptions)
      }
    
      vertx.eventBus().request<String>("test-address", Foo(), genericDeliveryOptions) {
        println(it.result().body())
      }
    
      vertx.close()
    }
    
    data class Foo(
      val foo: String = "foo",
    )
    
    data class Bar(
      val bar: String = "bar",
    )
    
    class GenericCodec : MessageCodec<Any, Any> {
      companion object {
        const val NAME = "generic"
      }
    
      private val mapper: ObjectMapper = ObjectMapper()
    
      override fun encodeToWire(buffer: Buffer, s: Any) {
        buffer.appendBytes(mapper.writeValueAsBytes(s))
      }
    
      override fun decodeFromWire(pos: Int, buffer: Buffer): Any {
        throw RuntimeException("should never get here, unless using clustered mode")
      }
    
      override fun transform(s: Any): Any {
        return s
      }
    
      override fun name(): String {
        return NAME
      }
    
      override fun systemCodecID(): Byte {
        return -1
      }
    }
    
    val genericDeliveryOptions = deliveryOptionsOf(codecName = GenericCodec.NAME)