码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 基于 .net core 8.0 的 swagger 文档优化分享-根据命名空间分组显示


    基于 .net core 8.0 的 swagger 文档优化分享-根据命名空间分组显示 之前也分享过 Swashbuckle.AspNetCore 的使用,不过版本比较老了,本次演示用的示例版本为 .net core 8.0,从安装使用开始,到根据命名空间分组显示,十分的有用
    合集 - DotNetCore(23)
    1.04.使用 github actions+docker 自动部署前后端分离项目 zhontai (.net core+vue)2023-08-282..net core建站踩坑记录2017-07-103.mvc网站迁移.net core记录2017-07-254.asp.net core合并压缩资源文件引发的学习之旅2017-09-285..NET Core+Selenium+Github+Travis CI => SiteHistory2017-08-306.dotnet使用Selenium执行自动化任务2017-08-277.docker发布netcore网站-零散记录2017-08-248.Swashbuckle.AspNetCore3.0的二次封装与使用2018-10-039..net core2.1 使用 dynamic 类型报错2018-06-2010.常用cmd代码片段及.net core打包脚本分享2018-04-0811.asp.net core使用Swashbuckle.AspNetCore(swagger)生成接口文档2018-01-2212.ubuntu下查看-卸载软件(卸载.net core sdk的方法)2018-01-2113.asp.net core封装layui组件示例分享2017-10-0914.asp.net core后台系统登录的快速构建2017-09-3015.asp.net core权限模块的快速构建2017-09-28
    16.基于 .net core 8.0 的 swagger 文档优化分享-根据命名空间分组显示07-05
    17.构建 dotnet&vue 应用镜像->推送到 Nexus 仓库->部署为 k8s 服务实践01-0218.一个基于.NET7的开源DNS服务 DnsServer 的部署使用经验分享2023-11-0619.自定义构建基于.net core 的基础镜像2019-09-2820.三行脚本让 asp.net core 附加进程调试不再头痛2019-08-2821.dotnet-warp && NSSM 部署 .net core 项目到 windows 服务2019-04-2922.在 ASP.NET Core 中使用 MySql 踩坑记录2018-10-2323.在asp.net core2.1中添加中间件以扩展Swashbuckle.AspNetCore3.0支持简单的文档访问权限控制2018-10-04
    收起

    前言

    公司项目是是微服务项目,网关是手撸的一个.net core webapi 项目,使用 refit 封装了 20+ 服务 SDK,在网关中进行统一调用和聚合等处理,以及给前端提供 swagger 文档
    在我两年前进公司的时候,文档还能够顺滑的打开,在去年的时候文档只能在本地打开,或者访问原始的 swagger 页面,knife4j 的页面更是打不开一点,于是想办法对此进行了优化

    .net core 项目中使用 Swashbuckle.AspNetCore 生成 SwaggerUI

    首先再记录一下安装及使用,之前也分享过 Swashbuckle.AspNetCore 的使用,不过版本比较老了,本次演示用的示例版本为 .net core 8.0,从安装使用开始分享一二

    安装包

    • 新建.net core 项目
    • 添加 Swashbuckle.AspNetCore 相关包引用
    • 设置项目 xml 生成路径,组件将根据 xml 解析接口相关信息
      <ItemGroup>
        <PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
        <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.6.2" />
        <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.6.2" />
      ItemGroup>
    	<PropertyGroup>
    		<DocumentationFile>bin\$(MSBuildProjectName).xmlDocumentationFile>
    	PropertyGroup>
    

    服务配置

    • 一些基础配置使用备忘
      • 配置文档信息 c.SwaggerDoc
      • 配置环境 c.AddServer
      • 配置模型标识 c.CustomSchemaIds
      • 配置唯一标识 c.CustomOperationIds
      • 配置解析 xml c.IncludeXmlComments
      • 启用数据注解 c.EnableAnnotations [SwaggerOperation]
    • 完整配置如下
    //框架初始化巴拉巴拉xxx
    builder.Services.AddControllers();
    //配置 swagger
    UseSwagger(builder.Services);
    
    /// 
    /// Swagger 注入配置
    /// 
    /// 
    /// 
    void UseSwagger(IServiceCollection services)
    {
        services.AddSwaggerGen(c =>
        {
            //配置文档信息
            c.SwaggerDoc("v1", new OpenApiInfo
            {
                Title = "swagger接口文档测试",
                Description = "这是一个文档",
                Version = "v1",
            });
            //配置环境
            c.AddServer(new OpenApiServer()
            {
                Url = "",
                Description = "本地"
            });
            //配置模型标识,默认type.Name,名称一样,不同明明空间会报错,所以改成FullName,加上命名空间区分
            c.CustomSchemaIds(type => type.FullName);
            //配置唯一标识
            c.CustomOperationIds(apiDesc =>
            {
                var controllerAction = apiDesc.ActionDescriptor as ControllerActionDescriptor;
                return controllerAction.ControllerName + "-" + controllerAction.ActionName;
            });
            //解析站点下所有xml,一般加自己项目的引用的即可
            foreach (var file in Directory.GetFiles(AppContext.BaseDirectory, "*.xml"))
            {
                c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, file));
            }
            //启用数据注解
            c.EnableAnnotations(true, true);
        });
    }
    
    • 启用 swagger
    
    RunSwagger(app);
    
    /// 
    /// 启用swagger
    /// 
    /// 
    void RunSwagger(IApplicationBuilder app)
    {
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/v1/api-docs", "V1 Docs");
        });
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapSwagger("{documentName}/api-docs");
            endpoints.MapGet("/v3/api-docs/swagger-config", async (httpContext) =>
            {
                JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions
                {
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                    IgnoreNullValues = true
                };
                jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase, false));
                SwaggerUIOptions _options = new SwaggerUIOptions()
                {
                    ConfigObject = new ConfigObject()
                    {
                        Urls = new List
                            {
                                new UrlDescriptor()
                                {
                                    Url="/v1/api-docs",
                                    Name="V1 Docs"
                                }
                            }
                    }
                };
                await httpContext.Response.WriteAsync(JsonSerializer.Serialize(_options.ConfigObject, jsonSerializerOptions));
            });
        });
    }
    
    

    运行

    • 运行后可以看到配置成功,swagger文档已经生成

    到这里基础的 swagger 配置已可以使用,更深层次的参考官方文档使用即可,接下来才是不一样的东西
    随着我们的项目发展,当我们的服务越来越多,接口也越来越多的时候,swagger 就从慢,到打开超时偶尔能打开,到每次都打不开(/api-docs 过大返回超时,渲染卡顿)
    这个时候,或者一开始就应该对 swagger 进行分组返回了,优化 /api-docs 接口返回的数据
    当然,除了这种方式,还有可以加特效标记的方式,但是几百个服务,加不了一点

    分模块返回文档

    一开始并没有想到分组显示,因为在本地运行的时候是可以打开的,只是 json 文件较大,于是做了一个优化是每次在发布应用后,请求一个接口去将 swagger 的 json 文件生成到本地,后续访问直接读取,算是暂时解决了打不开的问题,这样用了大半年,实在受不了这个速度,然后平时在看一些开源项目的时候发现是完全可以按自己的规则进行分组的,于是有了这篇文章

    为了兼容之前的文档路由,所以还是在原有配置的基础上,配置了其他模块的接口文档
    可有两种方式

    • 一种是在原有基础上显示其他分组
    • 一种是单独的 swagger 进行显示

    优化修改

    • 先定义好需要分组显示的模块
    //设置需要分组的api接口
    var groupApis = new List<string>() { "SwaggerTest.Controllers.Test", "SwaggerTest.Controllers.Demo" };
    
    • UseSwagger 修改部分
    • 重点是这块的自定义,去分组中匹配路由 c.DocInclusionPredicate 官方文档
    //配置文档信息
    c.SwaggerDoc("v1", new OpenApiInfo
    {
        Title = "swagger接口文档测试",
        Description = "这是一个文档",
        Version = "v1",
    });
    //配置环境
    c.AddServer(new OpenApiServer()
    {
        Url = "",
        Description = "本地"
    });
    //模型标识配置,默认type.Name,名称一样,不同明明空间会报错,所以改成FullName,加上命名空间区分
    c.CustomSchemaIds(type => type.FullName);
    c.CustomOperationIds(apiDesc =>
    {
        var controllerAction = apiDesc.ActionDescriptor as ControllerActionDescriptor;
        return controllerAction.ControllerName + "-" + controllerAction.ActionName;
    });
    //加载注释文件
    foreach (var file in Directory.GetFiles(AppContext.BaseDirectory, "*.xml"))
    {
        c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, file));
    }
    //增加模块接口的注册
    groupApis.ForEach(s =>
    {
        c.SwaggerDoc(s, new OpenApiInfo
        {
            Title = "api-" + s,
            Description = "api " + s,
            Version = "v1",
        });
    });
    
    //启用数据注解
    c.EnableAnnotations(true, true);
    //自定义分组匹配
    c.DocInclusionPredicate((docName, apiDes) =>
    {
        if (groupApis.Contains(docName))
        {
            var displayName = apiDes.ActionDescriptor?.DisplayName?.ToLower() ?? string.Empty;
            var existGroup = groupApis.FirstOrDefault(s => displayName.Contains(s.ToLower()));
            return docName == existGroup;
        }
    
        return true;
    });
    
    • RunSwagger 修改部分
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/v1/api-docs", "V1 Docs");
        //默认页支持分组
        groupApis.ForEach(s =>
        {
            c.SwaggerEndpoint($"/{s}/api-docs", s);
        });
    });
    //单独的页面
    groupApis.ForEach(s =>
    {
        app.UseSwaggerUI(c =>
        {
            c.RoutePrefix = s;
            c.SwaggerEndpoint($"/{s}/api-docs", s);
        });
    });
    app.UseEndpoints(endpoints =>
    {
        SwaggerUIOptions _options = new SwaggerUIOptions()
        {
            ConfigObject = new ConfigObject()
            {
                Urls = new List
                    {
                        new UrlDescriptor()
                        {
                            Url="/v1/api-docs",
                            Name="V1 Docs"
                        }
                    }.Concat(groupApis.Select(s => new UrlDescriptor()
                            {
                                Url = $"/{s}/api-docs",
                                Name = s
                            }).ToList())
            }
        };
    })
    

    修改完成后,可以结合自己业务来定义需要单独显示分组,最近又基于此加了一个开放平台的接口,独立于正常网关,单独提供出去,一切都是刚刚好~

    后语

    如果有更好的方式,欢迎分享
    若有错误,欢迎指出,谢谢

    相关文档

    • Swashbuckle.AspNetCore
    • 一篇比较细致的 Swashbuckle 使用教程

    未经许可,禁止转载!!!
    作者:易墨
    Github:yimogit
    纯静态工具站点:metools

  • 相关阅读:
    【配电变电站的最佳位置和容量】基于遗传算法的最优配电变电站放置(Matlab代码实现)
    react 路由拦截通过tocken进行简单拦截
    Dockerfile命令详细讲解
    Springboot 集成 MongoDB
    uniapp本地存储的几种方式
    RibbonGroup
    RK3399平台开发系列讲解(CPU篇)常见CPU性能问题
    Nginx
    y _hat[ [ 0, 1], y ]语法——pytorch张量花式索引
    在互联网上做好这两件事,轻松年赚50w?
  • 原文地址:https://www.cnblogs.com/morang/p/18284628/netcore8-swagger-group-namespace-show
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号