1. 概述

API文档是应用开发的关键环节,它既是与客户端的共享契约,也详细记录了集成点的工作方式。好的文档应易于访问、理解和实现。

本文将介绍如何使用Springwolf为事件驱动的Spring Boot服务生成文档。Springwolf实现了AsyncAPI规范——这是OpenAPI规范在事件驱动API领域的适配版本。Springwolf是协议无关的,支持Spring Kafka、Spring RabbitMQ和Spring CloudStream等实现。

以Spring Kafka作为事件驱动系统,Springwolf能自动从代码生成AsyncAPI文档。部分消费者会被自动检测,其他信息则需手动提供。

2. 设置Springwolf

2.1 添加依赖

假设已有运行中的Spring Kafka应用,在pom.xml中添加springwolf-kafka依赖:

<dependency>
    <groupId>io.github.springwolf</groupId>
    <artifactId>springwolf-kafka</artifactId>
    <version>0.14.0</version>
</dependency>

最新版本可在Maven Central获取,其他绑定支持见项目官网。

2.2 application.properties配置

基础配置如下:

# Springwolf基础配置
springwolf.docket.base-package=com.example.demo
springwolf.docket.info.title=${spring.application.name}
springwolf.docket.info.version=1.0.0
springwolf.docket.info.description=Springwolf AsyncAPI文档示例应用

# Springwolf Kafka配置
springwolf.docket.servers.kafka.protocol=kafka
springwolf.docket.servers.kafka.url=localhost:9092

✅ 第一块设置通用配置,其中base-package用于自动检测监听器
✅ 第二块设置Kafka特定配置,这些信息会出现在AsyncAPI文档中

2.3 验证

启动应用后,默认可通过以下路径访问AsyncAPI文档:

http://localhost:8080/springwolf/docs

3. AsyncAPI文档结构

AsyncAPI文档结构与OpenAPI类似,核心部分包括:

{
    "asyncapi": "2.6.0",
    "info": { ... },
    "servers": { ... },
    "channels": { ... },
    "components": { ... }
}

3.1 info部分

包含应用基本信息,至少包含titleversiondescription

"info": {
    "title": "Springwolf示例应用",
    "version": "1.0.0",
    "description": "使用Springwolf生成AsyncAPI文档的示例应用"
}

3.2 servers部分

描述Kafka broker信息:

"servers": {
    "kafka": {
        "url": "localhost:9092",
        "protocol": "kafka"
    }
}

3.3 channels部分

初始为空,配置消费者/生产者后显示:

"channels": {
    "my-topic-name": {
        "publish": {
            "message": {
                "title": "IncomingPayloadDto",
                "payload": {
                    "$ref": "#/components/schemas/IncomingPayloadDto"
                }
            }
        }
    }
}

⚠️ 注意:channels在Kafka中对应topics
⚠️ 操作语义可能反直觉:

  • publish:向此通道发布消息(供应用消费)
  • subscribe:订阅此通道(接收应用发布的消息)

3.4 components部分

存储$ref引用的详细信息:

"components": {
    "schemas": {
        "IncomingPayloadDto": {
            "type": "object",
            "properties": {
                "someString": {
                    "type": "string"
                }
            },
            "example": {
                "someEnum": "FOO2",
                "someLong": 1,
                "someString": "string"
            }
        }
    }
}

4. 文档化消费者

Springwolf自动检测所有@KafkaListener注解,也可通过@AsyncListener手动补充信息。

4.1 自动检测@KafkaListener

base-package内的方法上使用@KafkaListener

@KafkaListener(topics = TOPIC_NAME)
public void consume(IncomingPayloadDto payload) {
    // 业务逻辑
}

✅ 自动生成TOPIC_NAME通道的publish操作和IncomingPayloadDto模式

4.2 手动文档化消费者

自动检测与手动注解同时使用可能导致重复。解决步骤:

  1. 禁用自动检测:

    springwolf.plugin.kafka.scanner.kafka-listener.enabled=false
    
  2. 添加Springwolf注解:

    @KafkaListener(topics = TOPIC_NAME)
    @AsyncListener(
     operation = @AsyncOperation(
         channelName = TOPIC_NAME,
         description = "消费主题的详细说明"
     )
    )
    @KafkaAsyncOperationBinding
    public void consume(IncomingPayloadDto payload) {
     // 业务逻辑
    }
    

@AsyncListener补充文档信息
@KafkaAsyncOperationBinding关联Kafka协议配置

5. 文档化生产者

生产者需通过@AsyncPublisher手动文档化:

@AsyncPublisher(
    operation = @AsyncOperation(
        channelName = TOPIC_NAME,
        description = "生产主题的详细说明"
    )
)
@KafkaAsyncOperationBinding
public void publish(OutgoingPayloadDto payload) {
    kafkaTemplate.send(TOPIC_NAME, payload);
}

✅ 自动从方法签名提取载荷类型
✅ 生成subscribe操作到channels部分

6. 增强文档

6.1 添加Kafka消息头

Spring Kafka默认添加__TypeId__头辅助反序列化。文档化方式:

@AsyncListener(
    operation = @AsyncOperation(
        ...,
        headers = @AsyncOperation.Headers(
            schemaName = "SpringKafkaDefaultHeaders",
            values = {
                @AsyncOperation.Headers.Header(
                    name = "__TypeId__",
                    description = "Spring类型ID头",
                    value = "com.example.dto.IncomingPayloadDto"
                )
            }
        )
    )
)

✅ 在message对象中添加headers字段

6.2 添加载荷细节

使用Swagger的@Schema注解增强载荷文档:

@Schema(description = "出站载荷模型")
public class OutgoingPayloadDto {
    @Schema(description = "Foo字段", example = "bar", requiredMode = NOT_REQUIRED)
    private String foo;

    @Schema(description = "入站载荷字段", requiredMode = REQUIRED)
    private IncomingPayloadDto incomingWrapped;
}

生成的文档示例:

"OutgoingPayloadDto": {
    "type": "object",
    "description": "出站载荷模型",
    "properties": {
        "incomingWrapped": {
            "$ref": "#/components/schemas/IncomingPayloadDto"
        },
        "foo": {
            "type": "string",
            "description": "Foo字段",
            "example": "bar"
        }
    },
    "required": ["incomingWrapped"],
    "example": {
        "incomingWrapped": {
            "someEnum": "FOO2",
            "someLong": 5,
            "someString": "示例字符串"
        },
        "foo": "bar"
    }
}

7. 使用Springwolf UI

7.1 添加springwolf-ui依赖

<dependency>
    <groupId>io.github.springwolf</groupId>
    <artifactId>springwolf-ui</artifactId>
    <version>0.8.0</version>
</dependency>

7.2 查看文档

访问http://localhost:8080/springwolf/asyncapi-ui.html查看交互式文档:

Springwolf UI界面

7.3 发布消息

Springwolf UI支持直接从浏览器发布消息:

消息发布界面

⚠️ 出于安全考虑默认禁用,需手动启用:

springwolf.plugin.kafka.publishing.enabled=true

8. 结论

本文展示了在Spring Boot Kafka应用中集成Springwolf的完整流程:

  1. 通过消费者自动检测生成基础AsyncAPI文档
  2. 使用手动注解增强文档细节
  3. 通过Springwolf UI实现可视化文档管理和消息测试

完整示例代码见GitHub仓库


原始标题:Documenting Spring Event-Driven API Using AsyncAPI and Springwolf | Baeldung