天天看点

浅析如何在Nancy中生成API文档

浅析如何在Nancy中生成API文档

简单介绍了如何在Nancy中生成一份API文档,并且探讨其在Nancy的内部实现原理。

前后端分离,或许是现如今最为流行开发方式,包括UWP、Android和IOS这样的手机客户端都是需要调用后台的API来进行数据的交互。

但是这样对前端开发和APP开发就会面临这样一个问题:如何知道每个API做什么?

可能,有人会在内部形成一份word文档、pdf;有人会建立一个单独的站点,然后将API的地址,参数等信息列在上面;有人会借助第三方的工具来生成一份文档等。

当然,这基本是取决于不同公司的规范。

说起API文档,就想到前段时间做的微信小程序,由于那个不完善的接口文档,从而导致浪费了很大一部分时间去询问接口相关的内容(用的是老的接口)。

为了处理这个问题,我认为,如果能在写某个API的时候就顺带将这个API的相关信息一并处理了是最好不过!

不过这并不是让我们写好一个接口后,再去打开word等工具去编辑一下这个API的信息,这样明显需要花费更多的时间。

下面就针对这一问题,探讨一下在Nancy中的实现。

其实,想在Nancy中生成API文档,是一件十分容易的事,因为作者thecodejunkie已经帮我们在Nancy内部提前做了一些处理

便于我们的后续扩展,这点还是很贴心的。

下面我们先来写点东西,后面才能写相应的API文档。

基本的CURD,没有太多的必要去解释这些内容。当然这里需要指出一点。

正常情况下,我们基本都是只写前面两个参数的,后面两个参数是可选的。由于我们后面需要用到每个路由的名字

所以我们需要用到这里的第4个参数(当前路由的名字),也就意味着我们要在定义的时候写多一点东西!

注: 1.x和2.x的写法是有区别的!示例用的2.x的写法,所以各位要注意这点!

以GET为例,方法定义大致如下

浅析如何在Nancy中生成API文档

API写好了,下面我们先来简单获取一下这些api的相关信息!

前面也提到,我们是要把这个api和api文档放到同一个站点下面,免去编辑这一步骤!

世间万物都是相辅相成的,我们不想单独编辑,自然就要在代码里面多做一些处理!

新起一个Module名为<code>DocModule</code>,将api文档的相关内容放到这个module中来处理。

没错,你没看错,就是这几行代码,就可以帮助我们去生成我们想要的api文档!其实最主要的是IRouteCacheProvider这个接口。

它的具体实现,会在后面的小节讲到,现在先着重于使用!

先调用这个接口的GetCache方法,以拿到缓存的路由信息,这个路由信息有必要来看一下它的定义,因为不看它的定义,我们根本就没有办法继续下去!

后续的查找都是依赖于这些缓存信息!

看了上面的定义,就可以清楚的知道要用SelectMany去拿到那个元组的内容。再取出元组的RouteDescription。

当然,这个时候我们取到的是所有的路由信息,这些信息都包含了什么内容呢?看看RouteDescription的定义就很清晰了。

在查询之后,我还过滤了那些名字为空的,不让它们显示出来。为什么不显示出来呢?理由也比较简单,像DocModule,我们只定义了一个路由

而且这个路由在严格意义上并不属于我们api的内容,而且这个路由也是没有定义名字的,所以显示出来的意义也不大。

过滤之后,就得到了最终想要的信息!简单起见,这里是先直接 返回一个json对象,便于查看有什么内容,便于在逐步完善后再把它结构化。

下面是最简单实现后的大致效果:

浅析如何在Nancy中生成API文档

在图中,可以看到GetProductList和GetProductByProductId这两个api的基本信息:请求的method,请求的路径和路由片段。

但是这些信息真的是太少了!连api描述都见不到,拿出来,肯定被人狠狠的骂一顿!!

下面我们要尝试丰富一下我们的接口信息!

要让文档充实,总是需要一个切入点,找到切入点,事情就好办了。仔细观察上面的效果图会发现,里面的metadata是空的。当然这个也就是丰富文档内容的切入点了。

从前面的定义可以看到,这个metadata是一个RouteMetadata的实例

这里对我们比较重要的是Raw这个属性,因为这个是在返回结果中的一部分,它是一个字典,键是类型,值是这个类型对应的实例。

先定义一个<code>CustomRouteMetadata</code>,用于返回路由的Metadata信息(可根据具体情况进行相应的定义)。这个<code>CustomRouteMetadata</code>就是上述字典Type。

定义好我们要显示的东西后,自然要把这些东西用起来,才能体现它们的价值。

要用起来还涉及到一个MetadataModule,这个命名很像NancyModule,看上去都是一个Module。

先定义一个<code>ProductsMetadataModule</code>,让它继承<code>MetadataModule&lt;RouteMetadata&gt;</code>,

具体实现如下:

这里的写法就和1.x里写NancyModule的内容是一样的,应该也是比较熟悉的。就不再累赘了。其中的desc是一个委托<code>Func&lt;RouteDescription, TMetadata&gt;</code>。

默认返回的是一个RouteMetadata实例,而要创建一个这样的实例还需要一个字典,所以大家能看到上面的代码中定义了一个字典。

并且这个字典包含了我们自己定义的信息,其中Group和Description是完全的自定义,其他的是从RouteDescription中拿。

当然,这里已经开了一个口子,想怎么定义都是可以的!

完成上面的代码之后,再来看看我们显示的结果

浅析如何在Nancy中生成API文档

可以看到我们添加的metadata相关的内容已经出来了!可能这个时候,大家也都发现了,似乎内容有那么点重复的意思!

因为这些重复,就会让人感觉这里比较臃肿,所以我们肯定不需要取出太多重复的东西,目前只需要metadata下面的这些就可以了。

下面来对其进行简化!

简化分为两步:

第一步简化:DocModule的简化。

其实,DocModule已经是相当的简单了,但是还能在简洁一点点。这里用到了RetrieveMetadata这个扩展方法来处理。

前面的做法是拿到路由的信息后,用了两个Select来查询,而且查询出来的结果有那么一点臃肿,

而借助扩展方法,可以只取metadata里面的内容,也就是前面自定义的内容,这才是我们真正意义上要用到的。

下面是具体实现的示例:

经过第一步简化后,已经过滤了不少重复的信息了,效果如下:

浅析如何在Nancy中生成API文档

第二步简化:Metadata的简化

在返回Metadata的时候,我们是返回了一个默认的<code>RouteMetadata</code>对象,这个对象相比自定义的<code>CustomRouteMetadata</code>复杂了不少

而且从上面经过第一步简化后的效果图也可以发现,只有value节点下面的内容才是api文档需要的内容。

所以还要考虑用自定义的这个CustomRouteMetadata去代替原来的。

修改如下:

由于<code>MetadataModule&lt;TMetadata&gt;</code> 中的TMetadata是自定义的<code>CustomRouteMetadata</code>,所以在返回的时候直接创建一个简单的实例即可

不需要像<code>RouteMetadata</code>那样还要定义一个字典。

同时,还要把<code>DocModule</code>中RetrieveMetadata的TMetadata也要替换成CustomRouteMetadata

经过这两步的简化,现在得到的效果就是我们需要的结果了!

浅析如何在Nancy中生成API文档

最后,当然要专业一点,不能让人只看json吧!怎么都要添加一个html页面,将这些信息展示出来:

浅析如何在Nancy中生成API文档

当然,现在看上去还是很丑,文档内容也并不丰富,但是已经把最简单的文档做出来了,想要进一步丰富它就可以自由发挥了。

既然这样简单的代码就能帮助我们去生成api文档,很有必要去研究一下Nancy帮我们做了什么事!

从最开始的IRouteCacheProvider入手,这个接口对应的默认实现DefaultRouteCacheProvider

里面的GetCache方法是直接调用了定义的委托变量。最终是到了IRouteCache的实现类RouteCache,这个类算是一个重点观察对象!

内容有点多,就只贴出部分核心代码了

它在构造函数里去生成了路由的相关信息。

具体的生成方法如下:遍历所有的NancyModule,找到每个Module的RouteDescription集合(一个Module可以包含多个路由)

然后找到每个RouteDescription的描述,路由片段和metadata的信息。最后把这个Module路由信息添加到当前的对象中!

前面提到RouteDescription的描述,路由片段和metadata的信息都是通过额外的方式拿到的,这里主要是拿metadata来做说明

毕竟在上面最后的一个例子中,用到的是metadata的内容。

先调用定义的私有方法GetRouteMetadata,这个方法里面的内容是不是和前面的MetadataModule有点类似呢,字典和创建RouteMetadata的实例。

重点的是provider。这个provider来源来IRouteMetadataProvider,这个接口就两个方法。

Nancy这个项目中还有一个抽象类是继承了这个接口的。但是这个抽象类是没有默认实现的。

注:前面的原理分析都是基于Nancy这个项目。

这个时候,另外一个项目Nancy.Metadata.Modules就起作用了。我们编写的MetadataModule也是要添加这个的引用才能正常使用的。

从上面编写的MetadataModule可以看出这个项目的起点应该是MetadataModule,而且有关metadata的核心也在这里了。

到这里,已经将GetCache的内内外外都简单分析了一下。至于扩展方法RetrieveMetadata就不在细说了,只是selectmany和select的一层封装。

本文粗略讲解了如何在Nancy中生成API文档,以及简单分析了其内部的处理。

浅析如何在Nancy中生成API文档

下一篇将继续介绍这一块的内容,不过主角是Swagger。

浅析如何在Nancy中生成API文档

如果您认为这篇文章还不错或者有所收获,可以点击右下角的【推荐】按钮,因为你的支持是我继续写作,分享的最大动力!

作者:Catcher Wong ( 黄文清 )

来源:http://catcher1994.cnblogs.com/

声明:

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果您发现博客中出现了错误,或者有更好的建议、想法,请及时与我联系!!如果想找我私下交流,可以私信或者加我微信。

继续阅读