You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成Axon框架启动报错:快照使用默认XStreamSerializer未指定安全上下文

问题:Axon Framework启动报错:未指定安全上下文的默认XStreamSerializer用于快照

错误信息

org.axonframework.common.AxonConfigurationException: A default XStreamSerializer is used for snapshots, without specifying the security context
    at org.axonframework.eventsourcing.eventstore.AbstractEventStorageEngine$Builder.validate(AbstractEventStorageEngine.java:369) ~[axon-eventsourcing-4.5.8.jar:4.5.8]
    at org.axonframework.eventsourcing.eventstore.BatchingEventStorageEngine$Builder.validate(BatchingEventStorageEngine.java:224) ~[axon-eventsourcing-4.5.8.jar:4.5.8]
    at org.axonframework.extensions.mongo.eventsourcing.eventstore.MongoEventStorageEngine$Builder.validate(MongoEventStorageEngine.java:286) ~[axon-mongo-4.4.jar:4.4]
    at org.axonframework.eventsourcing.eventstore.AbstractEventStorageEngine.<init>(AbstractEventStorageEngine.java:74) ~[axon-eventsourcing-4.5.8.jar:4.5.8]
    at org.axonframework.eventsourcing.eventstore.BatchingEventStorageEngine.<init>(BatchingEventStorageEngine.java:62) ~[axon-eventsourcing-4.5.8.jar:4.5.8]
    at org.axonframework.extensions.mongo.eventsourcing.eventstore.MongoEventStorageEngine.<init>(MongoEventStorageEngine.java:64) ~[axon-mongo-4.4.jar:4.4]
    at org.axonframework.extensions.mongo.eventsourcing.eventstore.MongoEventStorageEngine$Builder.build(MongoEventStorageEngine.java:275) ~[axon-mongo-4.4.jar:4.4]
    at com.example.demo.configuration.AxonConfig.eventStorageEngine(AxonConfig.java:70) ~[classes/:na]
    // 省略后续栈跟踪信息

当前AxonConfig配置

package com.example.demo.configuration;

import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import org.axonframework.eventhandling.tokenstore.TokenStore;
import org.axonframework.eventsourcing.EventCountSnapshotTriggerDefinition;
import org.axonframework.eventsourcing.SnapshotTriggerDefinition;
import org.axonframework.eventsourcing.Snapshotter;
import org.axonframework.eventsourcing.eventstore.EmbeddedEventStore;
import org.axonframework.eventsourcing.eventstore.EventStorageEngine;
import org.axonframework.eventsourcing.eventstore.EventStore;
import org.axonframework.extensions.mongo.DefaultMongoTemplate;
import org.axonframework.extensions.mongo.MongoTemplate;
import org.axonframework.extensions.mongo.eventsourcing.eventstore.MongoEventStorageEngine;
import org.axonframework.extensions.mongo.eventsourcing.eventstore.MongoFactory;
import org.axonframework.extensions.mongo.eventsourcing.eventstore.MongoSettingsFactory;
import org.axonframework.extensions.mongo.eventsourcing.tokenstore.MongoTokenStore;
import org.axonframework.serialization.Serializer;
import org.axonframework.spring.config.AxonConfiguration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Configuration
public class AxonConfig {

    @Value("${spring.data.mongodb.host:127.0.0.1}")
    private String mongoHost;

    @Value("${spring.data.mongodb.port:27017}")
    private int mongoPort;

    @Value("${spring.data.mongodb.database:user-api}")
    private String mongoDatabase;

    @Bean
    public MongoClient mongoClient() {
        MongoFactory mongoFactory = new MongoFactory();
        MongoSettingsFactory mongoSettingsFactory = new MongoSettingsFactory();
        mongoSettingsFactory.setMongoAddresses(List.of(new ServerAddress(mongoHost, mongoPort)));
        mongoFactory.setMongoClientSettings(mongoSettingsFactory.createMongoClientSettings());
        return mongoFactory.createMongo();
    }

    @Bean
    public MongoTemplate axonMongoTemplate() {
        return DefaultMongoTemplate.builder()
                .mongoDatabase(mongoClient(), mongoDatabase)
                .build();
    }

    @Bean
    public TokenStore tokenStore(Serializer serializer) {
        return MongoTokenStore.builder()
                .mongoTemplate(axonMongoTemplate())
                .serializer(serializer)
                .build();
    }

    @Bean
    public EventStorageEngine eventStorageEngine() {
        return MongoEventStorageEngine.builder()
                .mongoTemplate(
                        DefaultMongoTemplate.builder()
                                .mongoDatabase(mongoClient())
                                .build()
                )
                .build();
    }

    @Bean
    public EmbeddedEventStore eventStore(AxonConfiguration configuration) {
        return EmbeddedEventStore.builder()
                .storageEngine(eventStorageEngine())
                .messageMonitor(configuration.messageMonitor(EventStore.class, "eventStore"))
                .build();
    }
}

解决方案

错误原因

Axon Framework 4.5+版本强化了序列化安全校验,默认的XStreamSerializer未配置安全上下文(白名单)时,不能用于快照序列化,否则会触发安全风险校验错误。

修复步骤

  1. 复用已配置的MongoTemplate:原代码中eventStorageEngine()方法重新创建了MongoTemplate,改为复用已定义的axonMongoTemplate() bean,避免重复实例化。
  2. 为快照序列化指定安全的Serializer:优先使用JacksonSerializer(无XStream的安全风险),若需使用XStream则必须配置允许的类/包白名单。

方案一:使用JacksonSerializer作为快照序列化器(推荐)

修改eventStorageEngine()方法,注入Axon默认提供的Serializer和JacksonSerializer:

@Bean
public EventStorageEngine eventStorageEngine(Serializer defaultSerializer, Serializer jacksonSerializer) {
    return MongoEventStorageEngine.builder()
            .mongoTemplate(axonMongoTemplate())
            .eventSerializer(defaultSerializer) // 事件使用默认序列化器
            .snapshotSerializer(jacksonSerializer) // 快照使用JacksonSerializer
            .build();
}

方案二:配置XStreamSerializer安全上下文(不推荐,存在安全风险)

若坚持使用XStream,需配置允许的包白名单:

@Bean
public Serializer snapshotSerializer() {
    return XStreamSerializer.builder()
            // 允许自己项目下的所有类
            .allowTypesByWildcard("com.example.demo.**")
            // 可添加其他需要允许的框架类
            .allowTypesByWildcard("org.axonframework.**")
            .build();
}

@Bean
public EventStorageEngine eventStorageEngine(Serializer defaultSerializer) {
    return MongoEventStorageEngine.builder()
            .mongoTemplate(axonMongoTemplate())
            .eventSerializer(defaultSerializer)
            .snapshotSerializer(snapshotSerializer())
            .build();
}

额外优化

原eventStore()方法无需修改,保持原样即可。

内容的提问来源于stack exchange,提问作者PAA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 19:06:27