通过Vertx中的事件总线发送对象集合的最佳方法是什么?

时间:2019-11-19 18:54:59

标签: java vert.x vertx-eventbus

我有一个处理程序,可在给定的端点上处理HTTP请求。处理程序通过事件总线向顶点发送消息,该事件总线进行一些外部分页的REST调用,汇总结果,然后将结果返回给处理程序。分页的REST调用的结果表示为自定义对象列表。如果我只是尝试发送List本身,则Vertx会引发异常,抱怨它找不到java.util.ArrayList的编解码器。

我试图在Vertx中找到“最佳”(意思是最简单,最有效,最易读/可维护)的方法,以将这些对象的列表通过事件总线发送回我的处理程序。这些是我目前所知道并且已经尝试过的选项,是否有更好的方法来实现这一目标?

  1. 将列表序列化为JSON并存储在JsonObject中。这要求在两端进行显式的序列化/反序列化,这似乎是不必要的:
// Verticle
List<CustomObject> result = method();
JsonObject data = new JsonObject();
data.put("result", Json.encode(result));
msg.reply(data);

// Handler
String serializedList = body.getString("result");
List<CustomObject> list = objectMapper.readValue(serializedList, new TypeReference<List<CustomObject>>(){});

  1. ArrayList<CustomObject>定义消息编解码器。从理论上讲,我相信这会行得通,但是我在网上看到的所有消息编解码器示例始终都是为单个对象创建编解码器,但我不确定这是否适用集合。

有没有一种更适合我不知道的用例的方法?谢谢!

1 个答案:

答案 0 :(得分:1)

很抱歉,给出一个冗长的示例,但是您可以在这里进行:

public class EventBusHolder {

    public static void main(String[] args) {
        Vertx vertx = Vertx.vertx();

        vertx.eventBus().registerDefaultCodec(Holder.class, new HolderCodec());
        vertx.deployVerticle(new SomeVerticle(), (r) -> {
            vertx.eventBus().send("custom", new Holder(new CustomObject("a")));
        });
    }
}

class HolderCodec implements MessageCodec<Holder, Holder> {

    @Override
    public void encodeToWire(Buffer buffer, Holder holder) {

    }

    @Override
    public Holder decodeFromWire(int pos, Buffer buffer) {
        return null;
    }

    @Override
    public Holder transform(Holder holder) {
        return holder;
    }

    @Override
    public String name() {
        return "HolderCodec";
    }

    @Override
    public byte systemCodecID() {
        return -1;
    }
}

class SomeVerticle extends AbstractVerticle {

    @Override
    public void start() {
        vertx.eventBus().consumer("custom", (msg) -> {
           System.out.println(msg.body());
        });
    }
}

class CustomObject {
    public String name;

    public CustomObject(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "CustomObject{" +
                "name='" + name + '\'' +
                '}';
    }
}


final class Holder {
    @Override
    public String toString() {
        return "Holder{" +
                "data=" + data +
                '}';
    }

    private final List<CustomObject> data;

    public Holder(final CustomObject... data) {
        this.data = Arrays.asList(data);
    }

    public List<CustomObject> getData() {
        return data;
    }
}

请注意,encodeToWiredecodeFromWire未实现。本地消息不会调用它们。

拥有这个Holder对象是在JVM上解决类型擦除的一种简便方法。