soda docs v17.0.1

版本与兼容

当前版本:17.0.1。

重要

最新版本以 Maven 仓库为准。 本页的版本号在文档构建时自动填入,可能略滞后于仓库。查 com.hibuka.soda:soda-core-base 的仓库页,或看 发布记录。

依赖坐标

soda 有两个模块:

模块groupIdartifactId用途
核心com.hibuka.sodasoda-core-base命令总线、查询总线、事件总线、CQRS 切面、领域事件、上下文传递
Redis 扩展com.hibuka.sodasoda-event-redisRedis Streams 事件总线,消费组、幂等、死信流

核心依赖

xml
<dependency>
  <groupId>com.hibuka.soda</groupId>
  <artifactId>soda-core-base</artifactId>
  <version>17.0.1</version>
</dependency>

Gradle:

groovy
implementation 'com.hibuka.soda:soda-core-base:17.0.1'

Redis 扩展(可选)

xml
<dependency>
  <groupId>com.hibuka.soda</groupId>
  <artifactId>soda-event-redis</artifactId>
  <version>17.0.1</version>
</dependency>
提示

soda-event-redis 是可选的。只用进程内事件总线的工程不用加这个依赖 —— 包体小很多,也没有 Redis 依赖。

用 Maven 属性管理版本更方便:

xml
<properties>
  <soda.version>17.0.1</soda.version>
</properties>

<dependencies>
  <dependency>
    <groupId>com.hibuka.soda</groupId>
    <artifactId>soda-core-base</artifactId>
    <version>${soda.version}</version>
  </dependency>
</dependencies>

环境要求

项要求
JDK17 或更高(推荐 21)
Spring Boot3.2.x ~ 4.1.x,同一个 jar 通吃
构建工具Maven / Gradle 均可
数据库框架不绑定,仓储层自己实现
Redis只有用 soda-event-redis 才需要
重要

soda-core 内部是在 Spring Boot 4.1.0 上开发和测试的,但编译目标是 Java 17(maven.compiler.release=17),并且通过 EventSerializer 抽象做到了 Jackson 2 / Jackson 3 双兼容。所以 Spring Boot 3.2.x 的工程可以直接用同一个坐标,不需要换 jar。

Spring Boot 版本的对应

Spring BootJacksonJackson 包名soda 里的 starter
3.2.xJackson 2com.fasterxml.jackson.*spring-boot-starter-web / spring-boot-starter-aop
4.xJackson 3tools.jackson.*spring-boot-starter-webmvc / spring-boot-starter-aspectj
注意

Spring Boot 4 改了 starter 的名字。soda-core 依赖的是 spring-boot-starter-aspectj(切面需要它),所以你的工程如果还在用旧的 spring-boot-starter-aop,要确认 aspectjweaver 在 classpath 上,否则切面不会生效 —— 表现为「事件永远发不出去」,且没有任何报错。

soda 自己用 spring-boot-dependencies 做 BOM 管理:

xml
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>${spring-boot.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
技巧

你的工程只要也引了 Spring Boot 的依赖管理,版本就自动对齐 —— soda 不需要单独指定 Spring Boot 版本。

soda 的传递依赖

soda-core-base 直接依赖:

依赖作用
spring-boot-autoconfigure自动装配的注解和条件
spring-boot-starter-aspectj@Aspect / @Around 支持
spring-boot-starter-validationjakarta.validation 约束注解
fastjson 1.2.83CqrsAroundHandler 里序列化日志用
lombok 1.18.46compile-only
knife4j-openapi3-spring-boot-starter 4.3.0Swagger / OpenAPI 注解

soda-event-redis 直接依赖:

依赖作用
soda-core-base核心
spring-boot-starter-data-redisRedis Stream 客户端
注意

fastjson 1.2.83 是编译期依赖,会传递到你的工程。1.x 系列有已知的历史 CVE。如果你的安全扫描会拦它,可以在工程里排除它 —— soda 内部只在 CqrsAroundHandler 里用它做日志序列化,Web 层那部分完全可以换成 Jackson。

xml
<dependency>
  <groupId>com.hibuka.soda</groupId>
  <artifactId>soda-core-base</artifactId>
  <version>17.0.1</version>
  <exclusions>
    <exclusion>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
    </exclusion>
  </exclusions>
</dependency>
提示

排除 fastjson 之后,CqrsAroundHandler 的日志序列化会失效(抛 NoClassDefFoundError)。如果你要排除它,就得同时自己定义一个 CqrsAroundHandler Bean 覆盖框架的 —— 而框架的切点表达式是硬编码在 CqrsAroundHandler 类里的,覆盖它意味着你要复制整个类。更实际的做法是:把 fastjson 换成安全版本,或者接受它。

版本号规则

soda 用的是 Java 基线版本方案:

text
<Java-major>.<feature>.<patch>
段含义例(17.0.1)
第一段最低 Java 版本17
第二段功能编号0
第三段补丁号1

所以 17.0.1 这个号按「最低 Java 第一段,功能第二段,补丁第三段」来读。拿 17.0.1 举例,就是「最低 Java 17,功能 0,补丁 1」。

技巧

这个方案的好处是:看到版本号就知道最低 Java 要求。2.1.0-boot32 这种旧版本号不遵循这个规则,是历史遗留。

历史版本对应关系

soda-core 版本支持的 Spring BootJava状态
17.x(当前)3.2.x ~ 4.1.x(同一个 jar)17+(推荐 21)活跃
17.0.04.x21不要用
4.0.04.x21已结束(历史)
2.1.1-boot323.2.x8已结束(Central 上只有 POM,没有 jar,用 2.1.0-boot32)
2.1.0-boot323.2.x8已结束
2.0.0 / 2.1.02.x8已结束
注意

17.0.0 不要用。 它是版本方案迁移时的一次误发布 —— 构建产物是旧的,缺少 EventSerializer 解耦,而且从未发布到 Maven Central,只被误推到了阿里云仓库。请直接用 17.0.1。

旧版本升级路径

从到要注意
4.0.017.0.1Java 17+;Spring Boot 3.2.x 也支持了;PageResult.success 参数顺序已经是新顺序
2.x17.0.1Java 8 → 17;Spring Boot 2.x → 3.2.x+;starter 名字变化;PageResult.success 参数顺序变化

跨大版本升级的完整清单见 从 v16 升级。

关于 Spring Boot 3 的几个具体差异

为了同时支持 Spring Boot 3 和 4,soda 做了几处适配。已知的差异点:

项Spring Boot 3Spring Boot 4
Web starterspring-boot-starter-webspring-boot-starter-webmvc
AOP starterspring-boot-starter-aopspring-boot-starter-aspectj
JSON starterspring-boot-starter-jsonspring-boot-starter-jackson
Jackson2.x3.x(包名变了)
Redis 自动配置类org.springframework.boot.autoconfigure.data.redis.RedisAutoConfigurationorg.springframework.boot.data.redis.autoconfigure.DataRedisAutoConfiguration

Redis 的自动配置类名在两个版本里不同,所以 RedisEventBusAutoConfiguration 用 @AutoConfigureAfter(name = {...}) 同时列了两个:

java
@AutoConfigureAfter(name = {
    "org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration",
    "org.springframework.boot.data.redis.autoconfigure.DataRedisAutoConfiguration"
})

RepositoryEventAutoConfiguration 里也列了两个自动配置类名:

java
@AutoConfigureAfter(name = {
    "com.hibuka.soda.event.spring.SpringEventBusAutoConfiguration",
    "com.hibuka.soda.event.redis.RedisEventBusAutoConfiguration"
})
提示

第一个名字 com.hibuka.soda.event.spring.SpringEventBusAutoConfiguration 指向的类已经不存在了(soda-event-spring 模块在 4.0.0 之后被移除)。@AutoConfigureAfter(name = ...) 遇到不存在的类名不会报错,只是这一条排序约束失效。因为另一个名字 RedisEventBusAutoConfiguration 还在,排序依然能工作。

校验安装是否成功

启动 Spring Boot,日志里应该能看到这几行:

text
[SimpleCommandBus] Constructor called, handlers size: 1
[SimpleCommandBus] Registered handler for command: com.example.demo.CreateProducerCommand
[SimpleEventBus] Constructor called, handlers size: 1
[SimpleEventBus] Registered 1 event handler types
[CqrsAroundHandler] Bean created!

数量对不上,说明 Handler 组件没被扫描到 —— 检查 @Component 和包路径。

下一步