Axon 2.4.6中XStreamSerializer序列化Byte数组转XML/dom4j方法问询
问题解决方案
前置校验
首先确认你存储的二进制数据的实际格式:把SerializedObject拿到的字节数组转成UTF-8字符串打印,判断是否为XML文本格式:
String xmlContent = new String((byte[]) serializedObject.getData(), StandardCharsets.UTF_8); System.out.println(xmlContent);
方案1:存储内容为XML文本字节(绝大多数场景的默认情况)
Axon 2.4.6的XStreamSerializer默认序列化结果为XML格式的字节流,你可以直接解析为dom4j结构修改后再反序列化:
- 解析字节流为dom4j对象
SAXReader saxReader = new SAXReader(); Document document = saxReader.read(new ByteArrayInputStream((byte[]) serializedObject.getData()));
- 调整XML结构,给新增字段设置默认值
// 找到MyEvent对应的节点,根据你实际的XML层级调整路径 Element myEventNode = document.getRootElement().element("myEvent"); // 给新增字段添加节点并赋值默认值 myEventNode.addElement("新增字段名").addText("默认值");
- 用和Axon配置完全一致的XStream实例反序列化
// 此处XStream的别名、类型转换器、忽略未知字段配置必须和Axon原生XStreamSerializer的配置保持一致 XStream xStream = new XStream(); MySaga saga = (MySaga) xStream.fromXML(document.asXML());
方案2:存储内容为XStream二进制编码格式
如果打印的字节内容为乱码,说明你之前使用了BinaryStreamDriver做二进制序列化,需要先通过XStream驱动转成dom4j结构:
// 初始化XStream时使用和序列化时一致的BinaryStreamDriver XStream xStream = new XStream(new BinaryStreamDriver()); HierarchicalStreamReader streamReader = xStream.createReader(new ByteArrayInputStream((byte[]) serializedObject.getData())); Dom4JReader domReader = new Dom4JReader(streamReader); Document document = domReader.getDocument(); // 后续修改XML、反序列化逻辑和方案1完全一致
方案3:符合Axon原生规范的Upcast实现
Axon 2.x本身提供了Saga版本升级的Upcaster机制,不需要自定义序列化器,直接实现SagaUpcaster接口即可:
public class MySagaUpcaster extends AbstractSingleEntryUpcaster<SerializedObject<?>> { public MySagaUpcaster() { // 匹配MySaga的初始版本号,这里假设你之前没有设置版本号,默认填1 super(new SimpleSerializedType(MySaga.class.getName(), "1")); } @Override protected SerializedObject<?> doUpcast(SerializedObject<?> intermediate, UpcastingContext context) { // 在这里完成序列化数据的修改逻辑,和上面的dom4j调整逻辑一致 byte[] modifiedData = 修改后的字节数组; // 返回修改后的序列化对象,版本号升级为2 return new SimpleSerializedObject<>(modifiedData, intermediate.getContentType(), new SimpleSerializedType(MySaga.class.getName(), "2")); } @Override public boolean canUpcast(SerializedType serializedType) { return MySaga.class.getName().equals(serializedType.getName()) && "1".equals(serializedType.getRevision()); } }
将这个Upcaster注册到你项目中SagaRepository绑定的序列化器配置中即可,该方式完全符合Axon的设计规范,不会侵入现有序列化逻辑。
注意事项
- 所有用到的XStream实例配置必须和Axon原生
XStreamSerializer的配置完全一致,避免出现类映射、字段解析异常 - 新增字段需要设置符合业务逻辑的默认值,避免反序列化后的Saga实例执行业务逻辑出错
内容的提问来源于stack exchange,提问作者lch
相关产品推荐
相关产品推荐

