【愚公系列】2023年02月 WMS智能仓储系统-007.Swagger接口文档的配置

举报
愚公搬代码 发表于 2023/02/28 22:46:59 2023/02/28
【摘要】 前言Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法、参数和模型紧密集成到服务器端的代码,允许 API 来始终保持同步。Swagger 让部署管理和使用功能强大的 API 从未如此简单。Swagger 是一组围绕 OpenAPI 规范构建的开源工具,可以帮助您设计...

前言

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。

总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法、参数和模型紧密集成到服务器端的代码,允许 API 来始终保持同步。Swagger 让部署管理和使用功能强大的 API 从未如此简单。

Swagger 是一组围绕 OpenAPI 规范构建的开源工具,可以帮助您设计、构建、记录和使用 REST API。主要的 Swagger 工具包括:

  • Swagger Editor – 基于浏览器的编辑器,您可以在其中编写 OpenAPI 定义。
  • Swagger UI – 将 OpenAPI 定义呈现为交互式文档。
  • Swagger Codegen – 从 OpenAPI 定义生成服务器存根和客户端库。
  • Swagger Editor Next (beta) – 基于浏览器的编辑器,您可以在其中编写和查看OpenAPI和AsyncAPI定义。
  • Swagger Core – 与 Java 相关的库,用于创建、消费和使用 OpenAPI 定义。
  • Swagger Parser – 用于解析 OpenAPI 定义的独立库
  • Swagger APIDom – 提供单一的统一结构,用于跨各种描述语言和序列化格式描述 API。

Swagger 官网:https://swagger.io/
在这里插入图片描述
Swagger 文档:https://swagger.io/docs/specification/about/
在这里插入图片描述

一、Swagger接口文档的配置

1.安装包

Swashbuckle.AspNetCore
Swashbuckle.AspNetCore.Filters

在这里插入图片描述

2.注入

2.1 Swagger服务的注入

#region 添加接口文档
services.AddSwaggerService(configuration, AppContext.BaseDirectory);
#endregion

#region Swagger配置
app.UseSwaggerConfigure(configuration);
#endregion

在这里插入图片描述

2.2 appsetting.json的配置

"SwaggerSettings": {
  "Name": "ModernWMS",
  "ApiTitle": "ModernWMS_API",
  "ApiVersion": "V1.0",
  "ApiDescription": "ModernWMS_API",
  "SecurityDefinition": false,
  "XmlFiles": [
    "ModernWMS.Core.xml",
    "ModernWMS.WMS.xml"
  ]
}

在这里插入图片描述

2.3 Swagger服务的封装

/// <summary>
/// Swagger
/// </summary>
/// <param name="services">服务容器</param>
/// <param name="configuration">配置文件</param>
/// <param name="BaseDirectory">主目录</param>
private static void AddSwaggerService(this IServiceCollection services, IConfiguration configuration, string BaseDirectory)
{
    if (services == null)
    {
        throw new ArgumentNullException(nameof(services));
    }
    //获取Swagger配置文件
    var swaggerSettings = configuration.GetSection("SwaggerSettings");
    
    var provider = services.Configure<SwaggerSettings>(swaggerSettings).BuildServiceProvider();
    var settings = provider.GetService<IOptions<SwaggerSettings>>()?.Value;

    if (settings != null && settings.Name.Equals("ModernWMS"))
    {
        services.AddSwaggerGen(c =>
        {
            //遍历出全部的版本,做文档信息展示
            typeof(CustomApiVersion.ApiVersions).GetEnumNames().ToList().ForEach(version =>
            {
                //version为地址文档版本:/swagger/{version}/swagger.json,[Route("/api/v2/blog/Blogtest")]
                c.SwaggerDoc(version, new OpenApiInfo
                {
                    Title = settings.ApiTitle,
                    Version = settings.ApiVersion,
                    Description = settings.Description
                });
            });

            //xml文档生成和注释
            if (settings.XmlFiles != null && settings.XmlFiles.Count > 0)
            {
                settings.XmlFiles.ForEach(fileName =>
                {
                    if (File.Exists(Path.Combine(BaseDirectory, fileName)))
                    {
                        //xml生成的文件地址,true表示注释文件包含了控制器的注释
                        c.IncludeXmlComments(Path.Combine(BaseDirectory, fileName), true);
                    }
                });
            }

            c.OperationFilter<AddResponseHeadersFilter>();
            c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
            c.OperationFilter<SecurityRequirementsOperationFilter>();


            c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
            {
                Description = "please input Bearer {token}",
                Name = "Authorization",
                In = ParameterLocation.Header,
                Type = SecuritySchemeType.ApiKey
            });
            c.SwaggerGeneratorOptions.DescribeAllParametersInCamelCase = false;

        });
    }
}

在这里插入图片描述

/// <summary>
/// register Swagger
/// </summary>
/// <param name="app"></param>
/// <param name="configuration">配置文件</param>
private static void UseSwaggerConfigure(this IApplicationBuilder app, IConfiguration configuration)
{

    var swaggerSettings = configuration.GetSection("SwaggerSettings");

    if (swaggerSettings != null && swaggerSettings["Name"].Equals("ModernWMS"))
    {
        app.UseSwagger();

        app.UseSwaggerUI(c =>
        {
            typeof(CustomApiVersion.ApiVersions).GetEnumNames().OrderBy(e => e).ToList().ForEach(version =>
            {
                c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{swaggerSettings["Name"]} {version}");
            });

            c.IndexStream = () => Assembly.GetExecutingAssembly().GetManifestResourceStream("ModernWMS.Core.Swagger.index.html");
            c.RoutePrefix = "";

        });
    }
}

在这里插入图片描述

2.3.1 SwaggerDoc

1、配置

SwaggerDoc主要用来声明一个文档,以声明多个接口文档,比如按开发版本进行声明:

CustomApiVersion就是版本号

/// <summary>
/// custom version
/// </summary>
public class CustomApiVersion
{
    /// <summary>
    /// Api module
    /// </summary>
    public enum ApiVersions
    {
        /// <summary>
        /// Base
        /// </summary>
        Base,
        /// <summary>
        /// WMS
        /// </summary>
        WMS
    }
}
//遍历出全部的版本,做文档信息展示
typeof(CustomApiVersion.ApiVersions).GetEnumNames().ToList().ForEach(version =>
{
    //version为地址文档版本:/swagger/{version}/swagger.json,[Route("/api/v2/blog/Blogtest")]
    c.SwaggerDoc(version, new OpenApiInfo
    {
        Title = settings.ApiTitle,
        Version = settings.ApiVersion,
        Description = settings.Description
    });
});

在这里插入图片描述

因为我们现在有两个接口文档了,想要在swaggerUI中看得到,还需要在中间件中添加相关文件的swagger.json文件的入口

typeof(CustomApiVersion.ApiVersions).GetEnumNames().OrderBy(e => e).ToList().ForEach(version =>
{
    c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{swaggerSettings["Name"]} {version}");
});

在这里插入图片描述
2、使用配置多文档

[ApiExplorerSettings(GroupName = "Base")]

ApiExplorerSettings说明:

  • 未使用ApiExplorerSettings特性,表名属于每一个swagger文档
  • 使用ApiExplorerSettings特性表名该接口属于Base文档
  • ApiExplorerSettingsAttribute还有个IgnoreApi属性,如果设置成true,将不会在swagger页面展示该接口

但是我们并不会直接在控制器上使用这个特性因为要配置非常多,下面是额外的封装注册类

public class GroupNameActionModelConvention : IActionModelConvention
{
    public void Apply(ActionModel action)
    {
        if (action.Controller.ControllerName == "Home")
        {
            if (action.ActionName == "Get")
            {
                action.ApiExplorer.GroupName = "Base";
                action.ApiExplorer.IsVisible = true;
            }
            else if (action.ActionName == "Post")
            {
                action.ApiExplorer.GroupName = "WMS";
                action.ApiExplorer.IsVisible = true;
            }
        }
    }
}

//或

public class GroupNameControllerModelConvention : IControllerModelConvention
{
    public void Apply(ControllerModel controller)
    {
        if (controller.ControllerName == "Home")
        {
            foreach (var action in controller.Actions)
            {

                if (action.ActionName == "Get")
                {
                    action.ApiExplorer.GroupName = "Base";
                    action.ApiExplorer.IsVisible = true;
                }
                else if (action.ActionName == "Post")
                {
                    action.ApiExplorer.GroupName = "WMS";
                    action.ApiExplorer.IsVisible = true;
                }
            }
        }
    }
}

注入使用

services.AddControllers(options =>
{
    options.Conventions.Add(new GroupNameControllerModelConvention());
    //或
    options.Conventions.Add(new GroupNameActionModelConvention());
});

这两种方式实现的效果和使用ApiExplorerSettingsAttribute是一样的,细心的朋友可能会注意,action.ApiExplorer.GroupName与ApiExplorerSettingsAttribute.GroupName是对应的,action.ApiExplorer.IsVisible则与ApiExplorerSettingsAttribute.IgnoreApi是对应的

2.3.2 IncludeXmlComments

IncludeXmlComments是用于加载注释文件,Swashbuckle会从注释文件中去获取接口的注解,接口参数说明以及接口返回的参数说明等信息。

//xml文档生成和注释
if (settings.XmlFiles != null && settings.XmlFiles.Count > 0)
{
    settings.XmlFiles.ForEach(fileName =>
    {
        if (File.Exists(Path.Combine(BaseDirectory, fileName)))
        {
            //xml生成的文件地址,true表示注释文件包含了控制器的注释
            c.IncludeXmlComments(Path.Combine(BaseDirectory, fileName), true);
        }
    });
}

在这里插入图片描述

2.3.3 OperationFilter

Operation可以简单的理解为一个操作,因为swagger是根据项目中的接口,自动生成接口文档,就自然需要对每个接口进行解析,接口路由是什么,接口需要什么参数,接口返回什么数据等等,而对每个接口的解析就可以视为一个Operation。

  • OperationFilter是操作过滤器,这个方法需要一个实现类IOperationFilter接口的类型,而它的第二个参数arguments是这个类型实例化时传入的参数。
  • OperationFilter允许我们对已经生成的接口进行修改,比如可以添加参数,修改参数类型等等。
//开启权限小锁
c.OperationFilter<AddResponseHeadersFilter>();
c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
c.OperationFilter<SecurityRequirementsOperationFilter>();

//在header中添加token,传递到后台
//Swagger响应头#
//这里需要Nuget引用Swashbuckle.AspNetCore.Filters,oauth2需要写死,SecurityRequirementsOperationFilter中默认securitySchemaName = "oauth2";
//未添加该配置时,Bearer一直无法加入到JWT发起的Http请求的头部,无论怎么请求都会是401;
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
    Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\\",
    Name = "Authorization",
    In = ParameterLocation.Header,
    Type = SecuritySchemeType.ApiKey
});
c.SwaggerGeneratorOptions.DescribeAllParametersInCamelCase = false;

在这里插入图片描述

2.3.4 其他

1、DescribeAllParametersInCamelCase
方法表示将参数使用驼峰命名法处理

2、RoutePrefix

设置SwaggerUI的Index页面的地址,默认是swagger,也就是说可以使用http://host:port/swagger可以访问到SwaggerUI页面,如果设置成空字符串,那么久可以使用http://host:port直接访问到SwaggerUI页面了

3、IndexStream

Swagger的UI页面是嵌入的资源文件,默认值是:

app.UseSwaggerUI(options =>
{
    options.IndexStream = () => typeof(SwaggerUIOptions).GetTypeInfo().Assembly.GetManifestResourceStream("Swashbuckle.AspNetCore.SwaggerUI.index.html");
});

我们可以修改成自己的页面,比如Hello World:

app.UseSwaggerUI(options =>
{
    options.IndexStream = () => new MemoryStream(Encoding.UTF8.GetBytes("Hello World"));
});

在这里插入图片描述

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。