基于 .net core 8.0 的 swagger 文档优化分享-根据命名空间分组显示

前言

公司项目是是微服务项目,网关是手撸的一个.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).xml</DocumentationFile></PropertyGroup>

服务配置

  • 一些基础配置使用备忘
    • 配置文档信息 c.SwaggerDoc
    • 配置环境 c.AddServer
    • 配置模型标识 c.CustomSchemaIds
    • 配置唯一标识 c.CustomOperationIds
    • 配置解析 xml c.IncludeXmlComments
    • 启用数据注解 c.EnableAnnotations [SwaggerOperation]
  • 完整配置如下
//框架初始化巴拉巴拉xxx
builder.Services.AddControllers();
//配置 swagger
UseSwagger(builder.Services);/// <summary>
/// Swagger 注入配置
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
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);/// <summary>
/// 启用swagger
/// </summary>
/// <param name="app"></param>
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<UrlDescriptor>{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<UrlDescriptor>{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 使用教程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/738601.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安全帽佩戴检测算法

安全帽佩戴检测算法是铁路工程施工人员安全管理中的重点和难点,它对检测算法的准确 率与检测速度都有较高的要求。本文提出一种基于神经网络架构搜索的安全帽佩戴检测算法 NAS-YOLO。该神经网络架构由上、下行操作单元组成,采用二进制门策略对网络架构进行更 新,通过数据驱动…

人员跌倒识别检测算法

人员跌倒识别检测算法是基于视频的检测方法,通过对目标人体监测,当目标人体出现突然倒地行为时,自动监测并触发报警。 人员跌倒识别检测算法基于计算机识别技术,配合现场摄像头,自动识别如地铁手扶梯/楼梯、老幼活动区等公共场所人员摔倒行为,准确率高于90%,及时救援,提…

学校视频监控系统

学校视频监控系统可以借助分布在学校各处的传统监控摄像头对学校的日常生活进行实时安防监控,学校视频监控系统保障学校的日常安全以及对学生的人身财产安全进行及时预警。帮助学校在技术日益进步的当下,提升对学校的安防监控能力和日常管理的效率,使得学校在安防监控这方面…

读人工智能全传03分治策略

读人工智能全传03分治策略1. 黄金年代 1.1. 图灵在他发表的论文《计算机器与智能》中介绍了图灵测试,为人工智能学科迈出第一步做出了重大贡献 1.2. 美国在第二次世界大战后几十年里计算机技术发展的特色,也是美国在未来60年内确立人工智能领域国际领先地位的核心 1.3. 1955年…

[6.27~7.4 做题记录]

[6.27~7.4 做题记录] 暑假集训,记录一些有意义 (多半无意义) 题目,不定时更新。 概率期望DP OSU! 考虑设 \(E_i\) 为到第 \(i\) 次操作时的期望分数。我们发现从 \(x^3\) 到 \((x+1)^3\) 将加上 \(3x^2+3x+1\),我们考虑 \(x\) 和 \(x^2\) 的期望: \[x1_i=(x1_{i-1}+1)\time…

Power BI实用技巧——外部工具DAX studio

Power BI实用技巧——外部工具DAX studio 当你想要将Power BI表格对象数据导出,Power BI却告诉你:您的数据过大可能会执行一些数据抽样,点击继续导出一份CSV文件,却发现Power BI只能导出三万行数据,这该怎么办呢? 这里我们就要推荐一款非常实用的外挂级软件——DAX studi…

一款EF Core下高性能、轻量级针对分表分库读写分离的解决方案

前言 今天大姚给大家分享一款EF Core下高性能、轻量级针对分表分库读写分离的解决方案,开源(Apache License)的EF Core拓展程序包:ShardingCore。 ShardingCore项目介绍 ShardingCore是一款开源、简单易用、高性能、普适性,针对EF Core生态下的分表分库的扩展解决方案,支…

java中堆污染(heap pollution)以及@SafeVarargs注解使用

什么是堆污染 heap pollution堆污染发生在使用可变参数(varargs)或泛型时,将不兼容的类型插入到一个泛型对象中。这会导致在运行时尝试访问这些对象时发生 ClassCastException。例如:public static void heapPollutionExample(List<String>... stringLists) {Object[…

e语音 【删除文本右边字符】

删除 “#换行符”代码本文来自博客园,作者:__username,转载请注明原文链接:https://www.cnblogs.com/code3/p/18284992

从OpenAI停服看中国市场:国产替代崛起的机遇与挑战

一、OpenAI 停服事件背景 OpenAI 自 2020 年推出 GPT-3 以来,在全球范围内引起了极大的反响。其强大的自然语言处理能力使其成为许多企业和开发者的首选工具。然而,2024 年 6 月 25 日,许多中国用户收到了一封来自 OpenAI 的邮件,邮件中明确表示,自 2024 年 7 月 9 日起,…

云锵投资 2024 年 6 月简报

季报摘要行情:二次探底; 微盘策略:大幅回撤,逻辑基础小幅动摇,但继续运行; 本季度量化基金策略业绩:-4.3085%,中,全国排名:7532;平均 Beta:1.00; 本季度量化股票策略业绩:-16.8934%,差,全国排名:11198;平均 Beta:1.84;(优良中差,表明全国排名四位分) 行…

全网最适合入门的面向对象编程教程:09 类和对象的Python实现-类之间的关系,你知道多少?

本文主要对类之间的关系进行了基本介绍,包括继承、组合、依赖关系,并辅以现实中的例子加以讲解,同时说明了不同关系的特点和应用场景。全网最适合入门的面向对象编程教程:09 类和对象的 Python 实现-类之间的关系,你知道多少? 摘要: 本文主要对类之间的关系进行了基本介…

[LeetCode] 274. H-Index

意外的简单。 class Solution:def hIndex(self, citations: List[int]) -> int:sorted_list = sorted(citations, reverse=True)ret = 0for i,element in enumerate(sorted_list[:1000]):curr = min(i+1, element)if curr > ret:ret = currreturn ret

数据换机

图1为本系统的方法的流程示意图图2为首次拷贝到X中断需要遍历的文件示意图图3为非首次拷贝找到X中断点需要遍历的文件示意图 实现的功能支持换机对SD卡的数据迁移大文件按阈值切成切片文件小文件和切片文件按阈值分段拷贝切片文件的恢复小文件和切片文件从换机cache下恢复到三…

实战篇——文件上传漏洞upload-labs-master靶场实战一

实战篇——文件上传漏洞upload-labs-master靶场实战(1) 前端验证绕过 (1) 篡改js代码 直接上传一句话木马失败:查看页面源代码:可见前端通过checkFile函数对上传文件的后缀名进行了验证。 使用Tampermonkey自定义js脚本,用于删除form表单的onsubmit属性:启用脚本,刷新页面…

国产数据库人大金仓Kingbase数据迁移工具

转载:国产数据库人大金仓Kingbase数据迁移工具-CSDN博客 注意:Kingbase自带的迁移工具,只能从其它数据库迁移到Kingbase数据库 适配数据库安装的时候建议使用完全安装(数据库可以不启动),后续也可以全部默认(如安装数据库,相关 参数设置可参考人大金仓(Kingbase)部署…

selenium操作

selenium介绍开发使用有头浏览器,部署使用无界面浏览器 selenium工作原理利用浏览器原生的API,封装成一套更加面向对象的Selenium WebDriver API,直接操作浏览器页面里的元素,甚至操作浏览器本身(截屏,窗口大小,启动,关闭,安装插件,配置证书之类的) selenium模块与d…

《Deep Learning》(深度学习)中英文双版PDF免费下载

“深度学习”经典著作《Deep Learning》中文版pdf免费下载。 《Deep Learning》(深度学习)是一本皆在帮助学生和从业人员进入机器学习领域的教科书,以开源的形式免费在网络上提供,这本书是由学界领军人物 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 合力打造。中文…

微服务异常问题

多服务间,被依赖服务代码更新,依赖服务不生效问题被依赖服务代码更新后,jar包会更新 依赖服务并不是通过http直接调用依赖服务的代码,而是通过依赖jar包的方式,把被依赖服务更新后的jar包更新到依赖服务中即可。 举例: 有A服务,B服务;其中A服务依赖B服务。 当A服务有代…

深度学习--强化学习--基本概念Q V--94

目录1. 强化学习2. 马尔科夫链3. Q值和V值 1. 强化学习 首先我们需要明确,强化学习的任务是什么? 这用大白话说:就是我们希望用强化学习的方式,使智能体获得独立自主地完成某种任务的能力。 智能体学习和工作的地方,我们就称为环境。 注意!所谓独立自主,就是智能体一旦启…