abp vnext中swagger使用小结
文章目录
- 介绍
- 先决条件
- 具体说明
- 模块类添加
- Swagger配置类
- 1、接口分组
- 2、接口注释
- 3、JWT认证的安全锁显示
- 4、枚举注释的显示
- 总结
介绍
现在大多工作中用到的后端开发都是基于RESTFUL
的接口开发了,所以使用swagger
进行接口管理也就成了比较默认的方式。最近相对比较有时间,所以觉得可以把在abp vnext中使用swagger
的一些知识点进行一下总结。
先决条件
- VS 2019
- Abp VNext 的版本号:4.0.0
- Swashbuckle.AspNetCore 版本号:5.5.0
- Swashbuckle.AspNetCore.Filters 版本号:6.1.0
具体说明
因为abp vnext中对模块的概念使用比较多,所以这里我们也使用这种方式。将swagger
的相关配置放到单独的类库中,在XXX.HttpApi.Host
项目中添加相应的依赖模块来完成最终的swagger
配置工作。
我们已类库:Hbw.Test.Swagger
作为此文的说明案例。
模块类添加
添加一个TestSwaggerModule
类,具体代码如下:
using Volo.Abp;
using Volo.Abp.Modularity;namespace Hbw.Test.Swagger
{public class TestSwaggerModule : AbpModule{public override void ConfigureServices(ServiceConfigurationContext context){context.Services.AddSwagger();}public override void OnApplicationInitialization(ApplicationInitializationContext context){context.GetApplicationBuilder().UseSwaggerUI();}}
}
Swagger配置类
添加一个扩展类来完成swagger
的具体配置工作,类名为:TestSwaggerExtensions
。关于接口的配置,我主要介绍一下几个点:接口分组、接口注释添加、JWT认证的安全锁显示和枚举注释的显示等。
首先我们需要在此类中添加AddSwagger
和UseSwaggerUI
方法。具体形式如下:
public static IServiceCollection AddSwagger(this IServiceCollection services)
{...
}public static void UseSwaggerUI(this IApplicationBuilder app)
{...
}
1、接口分组
接口的分组主要通过SwaggerDoc
来完成,然后通过DocInclusionPredicate
方法完成具体的接口在哪个组中进行显示,最后通过SwaggerEndpoint
方法将配置好的分组内容放到对应的json
文件中。
下面我们来具体的看看实现的过程。
- SwaggerDoc
public static IServiceCollection AddSwagger(this IServiceCollection services)
{return services.AddSwaggerGen(options =>{options.SwaggerDoc("thridapi_v1", new OpenApiInfo{Title = "第三方数据API",Version = "v1",Description = "xxxxxxxxx系统第三方数据 v1.0 接口服务"});options.SwaggerDoc("system_v1", new OpenApiInfo{Title = "系统API",Version = "v1",Description = "xxxxxxxxx系统 v1.0 接口服务"});});
}
- DocInclusionPredicate
public static IServiceCollection AddSwagger(this IServiceCollection services)
{return services.AddSwaggerGen(options =>{...options.DocInclusionPredicate((docName, description) =>{if (!description.TryGetMethodInfo(out MethodInfo method)){return false;}/*使用ApiExplorerSettingsAttribute里面的GroupName进行特性标识* DeclaringType只能获取controller上的特性* 我们这里是想以action的特性为主* */var version = method.DeclaringType.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);if (version.Any()){return version.Any(v => v == docName);}//这里获取action的特性var actionVersion = method.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);if (actionVersion.Any()){return actionVersion.Any(v => v == docName);}return false;});});
}
说明:
1、如果DocInclusionPredicate
方法中直接返回true
,则显示所有的接口,分组也就无效了。
2、通过上面的方法,也可以把abp vnext中默认生成的接口进行隐藏。
- SwaggerEndpoint
public static void UseSwaggerUI(this IApplicationBuilder app)
{app.UseSwagger();app.UseSwaggerUI(c =>{c.SwaggerEndpoint("/swagger/thridapi_v1/swagger.json", "第三方数据API");c.SwaggerEndpoint("/swagger/system_v1/swagger.json", "系统API");c.RoutePrefix = string.Empty; // url 中不显示swagger});
}
在完成了上面所有配置后,还有一个地方需要处理才能实现最终的效果。那就是具体的api
接口方法上,或者webapi
的控制器上添加ApiExplorerSettings
属性。
[ApiExplorerSettings(GroupName = "system_v1")]
public string Hello(string name)
{return $"{name}你好";
}
因为上面使用的分组是
system_v1
,所以Hello
将会在这个分组中显示;如果使用的是thridapi_v1
,则其将在此分组中显示。
效果图
2、接口注释
要实现接口的注释显示,首先应该把相应类库的xml
文件生成出来。具体可以右击对应项目的【属性】,在【生成】选项卡中的【输出】部分,勾选“XML文档文件”即可。
然后在swagger
中进行相应的配置,代码如下:
public static IServiceCollection AddSwagger(this IServiceCollection services)
{return services.AddSwaggerGen(options =>{...//获取应用程序所在目录(绝对,不受工作目录影响,建议采用此方法获取路径)var basePath = Path.GetDirectoryName(typeof(TestSwaggerModule)Assembly.Location);var xmlPath = Path.Combine(basePath, "xxxxx.xml");//这个就是刚刚配置的xml文件名//默认的第二个参数是false,对方法的注释// 即swagger界面只有方法有注释,最上面的控制器没有注释// 而第二个参数为true, 则是controller的注释options.IncludeXmlComments(xmlPath, true);});
}
3、JWT认证的安全锁显示
直接上代码,如下:
public static IServiceCollection AddSwagger(this IServiceCollection services)
{return services.AddSwaggerGen(options =>{...var security = new OpenApiSecurityScheme{Description = "JWT模式授权,请输入 Bearer {Token} 进行身份验证",Name = "Authorization",In = ParameterLocation.Header,Type = SecuritySchemeType.ApiKey};// 必须 oauth2 这个名称options.AddSecurityDefinition("oauth2", security);options.AddSecurityRequirement(new OpenApiSecurityRequirement { {security, new List<string>() } });options.OperationFilter<AddResponseHeadersFilter>();options.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();options.OperationFilter<SecurityRequirementsOperationFilter>();});
}
4、枚举注释的显示
如果没记错的话,swagger
是从版本3.x
开始使用了新的什么协议,网上也有写文章介绍了显示枚举注释的方法,但是都是基于2.x
版本的介绍。最终找到一个类似的解决方法,稍加整理形成一下方法。
其实核心的思路都是通过自定义一个继承自IDocumentFilter
接口的类来完成枚举的注释显示。
具体直接看代码吧。
public class EnumDocumentFilter : IDocumentFilter
{public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context){Dictionary<string, Type> dict = GetAllEnum();foreach (var item in swaggerDoc.Components.Schemas){var property = item.Value;var typeName = item.Key;Type itemType = null;if (property.Enum != null && property.Enum.Count > 0){if (dict.ContainsKey(typeName)){itemType = dict[typeName];List<OpenApiInteger> list = new List<OpenApiInteger>();foreach (var val in property.Enum){list.Add((OpenApiInteger)val);}property.Description += DescribeEnum(itemType, list);}}}static Dictionary<string, Type> GetAllEnum(){Assembly ass = Assembly.Load("Hbw.Test.Domain.Shared");Type[] types = ass.GetTypes();Dictionary<string, Type> dict = new Dictionary<string, Type>();foreach (Type item in types){if (item.IsEnum){dict.Add(item.Name, item);}}return dict;}static string DescribeEnum(Type type, List<OpenApiInteger> enums){if (type == null){return string.Empty;}var enumDescriptions = new List<string>();foreach (var item in enums){var value = Enum.Parse(type, item.Value.ToString());var desc = GetDescription(type, value);if (string.IsNullOrEmpty(desc)){enumDescriptions.Add($"{item.Value}:{Enum.GetName(type, value)}; ");}else{enumDescriptions.Add($"{item.Value}:{Enum.GetName(type, value)}, {desc}; ");}}return $"<br/>{Environment.NewLine}{string.Join("<br/>" + Environment.NewLine, enumDescriptions)}";}static string GetDescription(Type t, object value){foreach (MemberInfo mInfo in t.GetMembers()){if (mInfo.Name == t.GetEnumName(value)){foreach (Attribute attr in Attribute.GetCustomAttributes(mInfo)){if (attr.GetType() == typeof(DescriptionAttribute)){return ((DescriptionAttribute)attr).Description;}}}}return string.Empty;}}
}
代码中的
GetAllEnum
方法中,第一行加载的程序集是定义枚举的类库文件,在abp vnext中也就是Hbw.Test.Domain.Shared
这个库,所以这里把相应的项目类库名称放在此处即可。
完成这个类的定义后,我们需要在添加安全锁的代码的最后添加如下代码即可。
options.DocumentFilter<EnumDocumentFilter>();
最终的枚举注释显示效果如下:
以上基本完成了swagger
的单独配置工作,而如果要使用它,我们还需要在Hbw.Test.HttpApi.Host
项目中的模块类上添加依赖,具体如下:
[DependsOn(...typeof(TestSwaggerModule))]
public class TestHttpApiHostModule : AbpModule
{...
}
总结
以上就是目前我在项目中使用到的swagger
的相关配置内容,这样处理的好处是,如果以后有新的配置需要添加,那单独修改这个类库即可,如果你希望把它形成nuget
包进行发布,也是很方便的。希望对你也有所帮助。
abp vnext中swagger使用小结相关推荐
- 四、Abp Vnext中使用Minio打造文件管理模块(上)
在Abp商业版本中已经提供了文件管理模块的,免费版本是没有的,本文将介绍如何使用Minio打造一个自己的文件管理模块. 在项目开始之前,需要先安装一个Minio服务,可以在本地pc或云主机中安装,具体 ...
- 六、Abp Vnext 中Efcore的多模块关联查询
abp框架提供了非常棒的模块开发体验,这些模块是可复用的,并且也适用于开发微服务:既然模块可以独立发布,那么它的数据库配置也是独立的,对于使用efcore的模块,每个模块中都包含一个不同的Dbcont ...
- ABP Vnext中使用Magicodes.IE导入导出
文章目录 ABP Vnext中使用Magicodes.IE导入导出 1.Moudle中配置 2.构造函数注入 3.导出 3.1 导出实体 3.2 导出 4.导入 4.1 导入实体 4.2 导入 5.[ ...
- ABP vNext中使用开源日志面板 LogDashboard
ABP vNext 使用 logdashboard 本文示例源码: https://github.com/liangshiw/LogDashboard/tree/master/samples/abpv ...
- 在 ABP vNext 中编写仓储单元测试的问题一则
一.问题 新项目是基于 ABP vNext 框架进行开发的,所以我要求为每层编写单元测试.在同事为某个仓储编写单元测试的时候,发现了一个奇怪的问题.他的对某个聚合根的 A 字段进行了更新,随后对某个导 ...
- 八、Abp Vnext中为模块添加设置管理
在项目中,我们要进行一些参数配置,通常是使用aspnetcore的配置系统,通过appsettings.json来存储配置参数:Abp框架也包含了一套完善的设备管理模块,使用它可以很方便的从不同维度获 ...
- 『ABP』ABP vNext中使用开源日志面板 LogDashboard
- ABP VNext从单体切换到微服务
注:此处的微服务只考虑服务部分,不考虑内外层网关.认证等. ABP VNext从单体切换到微服务,提供了相当大的便利性,对于各模块内部不要做任何调整,仅需要调整承载体即可. ABP can help ...
- ABP vNext 的实体与服务扩展技巧分享
使用 ABP vNext 有一个月左右啦,这中间最大的一个收获是:ABP vNext 的开发效率真的是非常好,只要你愿意取遵循它模块化.DDD 的设计思想.因为官方默认实现了身份.审计.权限.定时任务 ...
最新文章
- modoer点评系统3.5_丰田“奥拓”正式亮相,油耗3.5L,配软顶敞篷+四开门,或4万起...
- 苹果开始整治App Store恶意抄袭现象
- 一幅图看懂Python编程
- php使用redis持久化,redis如何持久化
- 用按钮控制游戏物件的开启及关闭
- Java List集合转换相关操作
- 京东商品及评论爬虫(selenium)
- C++ 长指针与指针的区别
- 七年师大,青春永不毕业
- 使用Gson 解析json文件
- Aria2 安装和使用全教程
- 【每日一题】一起冲击蓝桥杯吧——Day2【蓝桥真题】
- 【Python 高级】Python全栈体系(七)
- 常用的Transformation
- 如何删除PDF文档中的某一页
- AVFrame结构体中变量解释
- Vim配置及使用技巧
- 智慧城市篇 | 数字孪生智慧排水管网管理平台
- NAO机器人的多功能
- ITAIP 培训通知|第三期“信创经理人研修班”高级决策人员报名中
热门文章
- 米的换算单位和公式_小学三年级数学常用公式和单位换算,孩子复习宝典!
- ipad远程连接虚拟机linux,如何从ipad pro上通过SSH远程Linux
- java 编译class_.java文件怎样编译成.class文件,你值得一看的技巧
- 电商新春农历年春节海报还没设计?这是你需要的新年Banner灵感!
- 百搭电商背景素材,设计师应急PSD分层模板
- java rpc 框架 常用_常用的RPC架构系列---gRPC
- Linux内存管理 brk(),mmap()系统调用源码分析2:brk()的内存释放流程
- webapi 路由限制命名控件_什么是命名数据网络NDN?
- Ubuntu20.04搭建ftp服务(亲测通过)
- android studio的一个bug