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

如何在模块化单体架构中为Swashbuckle Swagger按模块拆分定义?

实现模块化单体架构下Swagger按模块分组展示

完全可以实现你的需求,核心思路是为每个模块生成独立的Swagger文档,通过过滤器筛选对应模块的端点,最后在Swagger UI中提供模块选择器。以下是具体实现步骤:

1. 为每个模块注册独立的Swagger文档

在Swagger配置中,遍历所有模块,为每个模块创建专属Swagger文档:

builder.Services.AddSwaggerGen(options =>
{
    var modules = builder.Services.BuildServiceProvider().GetRequiredService<IEnumerable<Module>>();
    foreach (var module in modules)
    {
        options.SwaggerDoc(module.RoutePrefix, new OpenApiInfo 
        { 
            Title = $"{module.Name} API", 
            Version = "v1" 
        });
    }
});

2. 实现文档过滤器,筛选模块专属端点

创建IDocumentFilter,根据当前Swagger文档的标识(模块RoutePrefix),仅保留对应模块的端点:

public class ModuleSwaggerDocumentFilter : IDocumentFilter
{
    private readonly IEnumerable<Module> _modules;

    public ModuleSwaggerDocumentFilter(IEnumerable<Module> modules)
    {
        _modules = modules;
    }

    public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
    {
        var targetModuleRoute = swaggerDoc.Name;
        var pathsToRemove = new List<KeyValuePair<string, OpenApiPathItem>>();

        foreach (var path in swaggerDoc.Paths)
        {
            var apiDesc = context.ApiDescriptions.FirstOrDefault(api => api.RelativePath == path.Key.TrimStart('/'));
            if (apiDesc?.ActionDescriptor is ControllerActionDescriptor controllerAction)
            {
                controllerAction.RouteValues.TryGetValue("module", out var moduleRoute);
                if (moduleRoute != targetModuleRoute)
                {
                    pathsToRemove.Add(path);
                }
            }
        }

        foreach (var path in pathsToRemove)
        {
            swaggerDoc.Paths.Remove(path.Key);
        }
    }
}

将过滤器注册到SwaggerGen中:

builder.Services.AddSwaggerGen(options =>
{
    // 保留之前的模块文档注册代码
    options.DocumentFilter<ModuleSwaggerDocumentFilter>();
});

3. 配置Swagger UI,启用模块选择器

在中间件配置中,为每个模块添加Swagger端点,Swagger UI顶部会自动生成模块下拉选择框:

app.UseSwaggerUI(options =>
{
    var modules = app.Services.GetRequiredService<IEnumerable<Module>>();
    foreach (var module in modules)
    {
        options.SwaggerEndpoint($"/swagger/{module.RoutePrefix}/swagger.json", module.Name);
    }
    options.DocumentTitle = "模块化单体API文档";
});

结合现有路由约定

你已通过ModuleRoutingConvention为每个Action添加了module路由值,该值会被上述文档过滤器用来匹配模块,确保每个Swagger文档仅展示对应模块的端点。

内容的提问来源于stack exchange,提问作者R.Haughton

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 10:03:12