欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】

程序员文章站 2022-07-07 08:22:22
近期一直在学习Asp.net Core,微软的文档太难看,都是英文翻译过来的,很不友好,感谢这个博客,从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】,让我入门了,刚学到这个Swagger时,我就有个需求,因为我之前写过的系统是分了不同的模块,模块里面再分控制器,不同模块经常会有相 ......

近期一直在学习asp.net core,微软的文档太难看,都是英文翻译过来的,很不友好,感谢这个博客,从壹开始前后端分离【 .net core2.0 +vue2.0 】,让我入门了,刚学到这个swagger时,我就有个需求,因为我之前写过的系统是分了不同的模块,模块里面再分控制器,不同模块经常会有相同名称的控制器,例如销售中心模块里有个合同管理控制器,采购中心模块里也有个合同管理控制器,而且我一个系统接口可能得上百个,那如果都在一个页面显示的话,那也太多了,所以我想能不能把接口进行分组。

在博客系统后面也有介绍到swagger:api多版本控制,带来的思考,还有网上查到的【dotnet core】swagger下简单的给webapi分组(我发现网上关于asp.net core的资料还是比较少),再结合我自己的需求修改了一下。

先说下我的想法:

定义一个系统分组枚举enum,包含我系统所有的控制器分组(或者版本),然后再定义一个特性attribute,可以接收刚才那个enum值,在需要分组的控制器类上面定义特性attribute,swagger根据系统分组枚举enum的值进行分组,将特性attribute的分组枚举值一样的归为同一个分组,没有加特性attribute的归在无分组下,最终效果如下

从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】

 

 

下面是我的代码,理解为主,不用完全按我写的

基础swagger的用法就不说的,具体可看 从壹开始前后端分离【 .net core2.0 +vue2.0 】这个大师关于swagger部分的教程,非常适合初级入门

在项目创建一个目录(apigroup),然后创建三个类,分别为apigroupattribute.cs(控制器特性),apigroupnames.css(系统分组枚举),groupinfoattribute.cs(给系统分组枚举值增加相关信息的特性,这个主要是用于在swagger分组时可关联title,version,description值)

从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】

 

 apigroupattribute.cs代码如下

using microsoft.aspnetcore.mvc.apiexplorer;
using system;
using system.collections.generic;
using system.linq;
using system.threading.tasks;

namespace itsys.apigroup
{
    /// <summary>
    /// 系统分组特性
    /// </summary>
    public class apigroupattribute : attribute, iapidescriptiongroupnameprovider
    {
        public apigroupattribute(apigroupnames name)
        {
            groupname = name.tostring();
        }
        public string groupname { get; set; }
    }
}

 apigroupnames.cs代码如下

using system;
using system.collections.generic;
using system.linq;
using system.threading.tasks;

namespace itsys.apigroup
{
    /// <summary>
    /// 系统分组枚举值
    /// </summary>
    public enum apigroupnames
    {
        [groupinfo(title ="登录认证",description ="登录认证相关接口",version ="v1")]
        auth,
        [groupinfo(title = "it", description = "登录认证相关接口")]
        it,
        [groupinfo(title = "人力资源", description = "登录认证相关接口")]
        hr,
        cw
    }
}

groupinfoattribute.cs代码如下

using system;
using system.collections.generic;
using system.linq;
using system.threading.tasks;

namespace itsys.apigroup
{
    /// <summary>
    /// 系统模块枚举注释
    /// </summary>
    public class groupinfoattribute : attribute
    {
        public string title { get; set; }
        public string version { get; set; }
        public string description { get; set; }
    }
}

 

打开startup.cs文件修改configureservices方法(为了方便查看,只列出关于swagger分组的关键代码)

public void configureservices(iservicecollection services)
{
    
    #region swagger
    services.addswaggergen(options =>
    {
        //遍历apigroupnames所有枚举值生成接口文档,skip(1)是因为enum第一个fieldinfo是内置的一个int值
        typeof(apigroupnames).getfields().skip(1).tolist().foreach(f =>
        {
            //获取枚举值上的特性
            var info = f.getcustomattributes(typeof(groupinfoattribute), false).oftype<groupinfoattribute>().firstordefault();
            options.swaggerdoc(f.name, new swashbuckle.aspnetcore.swagger.info
            {
                title = info?.title,
                version = info?.version,
                description = info?.description
            });
        });
        //没有加特性的分到这个nogroup上
        options.swaggerdoc("nogroup", new swashbuckle.aspnetcore.swagger.info
        {
            title = "无分组"
        });
        //判断接口归于哪个分组
        options.docinclusionpredicate((docname, apidescription) =>
        {
            if (docname == "nogroup")
            {
                //当分组为nogroup时,只要没加特性的都属于这个组
                return string.isnullorempty(apidescription.groupname);
            }
            else
            {
                return apidescription.groupname == docname;
            }
        });
}

修改configure方法

public void configure(iapplicationbuilder app, ihostingenvironment env)
{

    #region swagger
    app.useswagger();
    app.useswaggerui(options =>
    {
        //遍历apigroupnames所有枚举值生成接口文档,skip(1)是因为enum第一个fieldinfo是内置的一个int值
        typeof(apigroupnames).getfields().skip(1).tolist().foreach(f =>
        {
            //获取枚举值上的特性
            var info = f.getcustomattributes(typeof(groupinfoattribute), false).oftype<groupinfoattribute>().firstordefault();
            options.swaggerendpoint($"/swagger/{f.name}/swagger.json", info != null ? info.title : f.name);

        });
        options.swaggerendpoint("/swagger/nogroup/swagger.json", "无分组");
    });
    #endregion
}

然后你f6生成一下,没出错的话,就ctrl+f5看看,正常的话就会在swagger右上角看到分组了。

从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】

 

 在你需要进行分组的控制器上加上这个分组就ok了

从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】

 

目前是一个接口只归为一个分组,但可能实际中有些公用接口,会出现在多个分组模块里的,那可以将apigroupattribute增加一个string[]或apigroupnames[]属性,接收多个枚举值,或者定义多个apigroupattribute特性,不过在configureservices里的swagger的docinclusionpredicate分组过滤方法里,就不能单判断groupname参数了,可以利用参数apidescription反射得出接口控制器上的apigroupattribute特性,获取所有的apigroupnames枚举值,再进行判断,实现一个接口可以归为多个分组。