.NetFramework 中使用 WebApi ,在不讨论 微服务 的模式下,大部分都是以层来拆分库的 :

  • 基础设施
  • 数据存储层
  • 服务层
  • WeApi 层
  • 一些其它的功能库

项目结构可能会像下面这样子

有些人可能会将其中的 数据存储层服务层 按业务功能进行垂直拆分,

但是到了 WebApi 这层,就不得不把所向所有业务功能的 Controller 都堆在这儿了。

随着业务的堆积,WebApi 这层的代码量越来越大,耦合性也越来越强,越来越难维护。

……

………

…………

这时候,微服务 就出现了。

可是,微服务 给系统所带来的复杂程度是极高的,

在某些场景下,转 微服务 可以很好的解决这些问题,但是又会带来更多的新问题,

所以我们希望有一种模式,即能像 微服务 那样对代码进行垂直切分,又能保持简单易维护的 单体应用程序 模式。


打算在 单体应用程序 中解决这种趋于 臃肿 问题,我们可以借鉴 微服务 那种 按业务垂直拆分 的思想。

但是与 微服务 不同是,它依然是单启动程序,这个启动程序能够组织出散落在各个模块中的所有 WebApi 并暴露给外部。

换个角度思考,其实就是将业务 模块化

微软维护的 Ochard框架很好的实现了这些功能,但是使用 Orchard 可能会给你带来以下问题

  • 这是一个非常重型的框架,代码量比较大,运行速度不佳
  • 几乎没有什么中文的文档( 最多只能找到 HelloWorld 这样的浅显的教程 )
  • 官网文档是英文的,对阅读有较高的要求,而且速度很慢,需要使用正确的阅读方式
  • 系统中充斥着大量的隐匿约束( 在类型名称上的约束,前端更是使用了大量的 DynamicObject ,很难了解到到底包含了哪些可用 成员 )

....

于是我基于 Reface.AppStarter 开发了一套轻量级的模块化 WebApi 框架 【 Reface.AppStarter.WebApi 】,它实现了以下功能

  • 垂直拆分你的 WebApi Controller 至不同的 Library
  • 开箱即用的 Controller 构造函数注入
  • 具备 Reface.AppStarter 中的 EventBus 和 CommandBus 功能,可以很好的进行模块间的通信
  • 在 启动模块 决定启动哪些业务模块

使用 Reface.AppStarter.WebApi 很简单,它对原来的开发风格几乎没有什么影响,

下面将演示如何使用 Reface.AppStarter.WebApi 将 WebApi 项目拆分至各种模块

Step 1 - 创建空的 WebApi 项目

创建一个 WebApi 项目,但是你不需要在这里写任何的 Controller , 它只是你的启动程序,不需要为它编写任何与启动无关的代码。

为你的 WebApi 添加 Nuget 引用Reface.AppStarter 。

Step 2 - 创建业务库

创建业务 Library ,比如 Users,你将在这个 Library 中实现有关 Users 的所有功能,包括 Controller

通过 Nuget 引用 Reface.AppStarter.WebApi

Step 3 - 在业务库中编写控制器

Users Library 添加一个 Controllers 的目录,并编写你的控制器

[ApiRoute("hello")]
public class HelloController : ApiController
{
[Route]
public string Get()
{
return "HelloWorld!";
}
}

Reface.AppStarter.WebApi 包含了编写一个 WebApi 的所有依赖项。

因此你只要通过 Nuget 添加了 Reface.AppStarter.WebApi 就可以编写属于你的 ApiController

如果你需要向 控制器 中注入一些其它的组件,你只要通过构造函数注入即可:

[ApiRoute("hello")]
public class HelloController : ApiController
{
private readonly IHelloService helloService; public HelloController(IHelloService helloService)
{
this.helloService = helloService;
} [Route]
public string Get()
{
return "HelloWorld!";
}
}

Step 4 - 编写业务库的 AppModule

为你的 Users Library 编写一个 AppModule

Reface.AppStarter 框架模式下,每一个 Library 都至少要提供一个 AppModule ,以供给其它模块依赖。

你的 Users 也不例外,

UsersAppModule 需要使用 WebApi 功能,因此 UsersAppModule 要依赖 WebApiAppModule

[WebApiAppModule]
public class UsersAppModule : AppModule
{
}

如果你还需要 自动配置、自动 IOC / DI 注册装配,那你也可以根据你的需求添加其它的 AppModule

Step 5 - 让你的启动项目依赖 UsersAppModule

首先,你需要为你启动项目创建一个 AppModule ,比如 WebAppModule

[UsersAppModule]
public class WebAppModule : AppModule
{
}

然后你需要创建一个 Global.asax ,相信大家应该都知道这是个什么吧。

修改你的 Global.asax 文件,使其继承于 RefaceHttpApplication<T>  ,这里的 T ,就是你的 WebAppModule

public class MyWebApiApplication : RefaceHttpApplication<WebAppModule>
{
}

这样,就会在 Web 应用程序启动的时候,完成 Reface.AppStarter 中的所有过程。

提示 :

  • 这个 RefaceHttpApplication<T> 只是封装了 AppSetup.Start 的过程,你也可以不继承此类,并手动完成对 AppSetup 的启动。

Step 6 - 配置文件

通过 RefaceHttpApplication<T> 启动,会以站点根目录的 app.json 文件作为 Reface.AppStarter 框架内的配置文件。

Reface.AppStarter.WebApi  内只有一个 Config 类型,它允许重新定义所有 WebApi 的路由前缀

{
"WebApi": {
"Prefix": "myapi"
}
}

你可以通过修改这个 Prefix 来修改所有控制器的前缀名称,( 默认值是 api )。

Step  7 - 运行

运行你的启动程序吧,并键入 /myapi/hello 你就会看到 HelloController 虽然写在了别的 Library 里,但是依然可以成功的访问。

至此就介绍了 Reface.AppStarter.WebApi 中的主要功能。

有关 Reface.AppStarter 相关功能,可以阅读 《https://www.cnblogs.com/ShimizuShiori/p/12610668.html

有关 事件总线,会在后面的文章中向大家介绍。

如何将 .NetFramework WebApi 按业务拆分成多个模块的更多相关文章

  1. 将log4j2的配置文件log4j2.xml拆分成多个xml文件

    在日常的项目开发中,我们可能会使用log4j2分离系统日志与业务日志 ,这样一来,log4j2.xml 这个配置文件可能就会变得非常臃肿.庞大,那么我们可以将这个文件拆分成多个配置文件吗? 答案是肯定 ...

  2. 为什么要把系统拆分成分布式的,为啥要用Dubbo?

    阅读本文大概需要 6 分钟. 作者:yanglbme 1.面试题 为什么要进行系统拆分?如何进行系统拆分?拆分后不用 dubbo 可以吗? 2.面试官心里分析 从这个问题开始就进行分布式系统环节了,好 ...

  3. 电商架构设计-通过系统和业务拆分,遵循单一职责原则SRP,保障整个系统的可用性和稳定性

    个人观察 1.通过系统和业务拆分,遵循单一职责原则SRP,保障整个系统的可用性和稳定性. 2.单一职责原则SRP,真的很关键,广大程序员需要不断深入理解这个原则. 3.架构图是架构师的重要输出,通过图 ...

  4. UTF-8编码的字符串拆分成单字、获取UTF-8字符串的字符个数的代码及原理

    一.字符编码简介 1. ASCII码 在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(by ...

  5. Oracle字符串行拆分成列的三种方式

    Oracle字符串行拆分成列的三种方式 --muphy 开发过程中经常会遇到将前台多个值用逗号连接一同传递到后台查询,这个用逗号连接的字符串分隔的每个字符串分别对应Oracle数据库表的不同行. 如下 ...

  6. [Swift]LeetCode842. 将数组拆分成斐波那契序列 | Split Array into Fibonacci Sequence

    Given a string S of digits, such as S = "123456579", we can split it into a Fibonacci-like ...

  7. 将excel按照某一列拆分成多个文件(方案整理)

    1解决方案:将excel按照某一列拆分成多个文件 https://blog.csdn.net/ntotl/article/details/79141314 2遇到的问题:解决vbe6ext.olb不能 ...

  8. Oracle数据库字段数据拆分成多行(REGEXP_SUBSTR函数)

    做多选功能时为了简便,会在某个字段中存储多个值,保存时虽然省事,但后续的查询统计时还需要拆分数据才行,因此这时需要将字段内的值分成多行以便后续使用. 下面这个例子实现了字段内数据的拆分: --创建测试 ...

  9. sql 表值函数-将一个传入的字符串用2中分隔符拆分成临时表

    USE [tms]GO/****** Object: UserDefinedFunction [dbo].[fn_StrToTable_Double] Script Date: 2017/4/26 9 ...

随机推荐

  1. cocoapods安装以及ZXingObjC的安装

    因为项目要用到第三方包ZXingObjC,需要安装cocoapods.下面是我曲折的安装过程. 1.直接在终端内输入: sudo gem install cocoapods 我直接安装成功. 由于国内 ...

  2. Map - 与君初相识

    前言 生活中,我们常会看到这样一种集合:IP地址与主机名,身份证号与个人等,这种一 一对应的关系,就叫做映射.Java提供了专门的集合类用来存放这种对应关系的对象,即 java.util.Map 接口 ...

  3. LoadRunner 11破解方法:

    LoadRunner 11破解方法: 请严格安装顺序操作! a.用LR8.0中的mlr5lprg.dll.lm70.dll覆盖LR11安装目录下“bin”文件夹中的对应文件: b.运行deleteli ...

  4. 数据结构 5 哈希表/HashMap 、自动扩容、多线程会出现的问题

    上一节,我们已经介绍了最重要的B树以及B+树,使用的情况以及区别的内容.当然,本节课,我们将学习重要的一个数据结构.哈希表 哈希表 哈希也常被称作是散列表,为什么要这么称呼呢,散列.散列.其元素分布较 ...

  5. 【简说Python WEB】Flask-Moment

    目录 [简说Python WEB]Flask-Moment 系统环境:Ubuntu 18.04.1 LTS Python使用的是虚拟环境:virutalenv Python的版本:Python 3.6 ...

  6. 建议14:灵活使用Arguments

    Javascript支持Arguments机制.Arguments是一个为数组,可以通过数组下标形式获取该集合中传递给函数的参数值.例如:下面函数中,没有指定形参,但在函数体内通过Arguments对 ...

  7. 建议10:建议使用splice删除数组

    删除数组元素的方法有很多种,最简单就是利用length属性来截断数组,但这种方法比较笨,进能够截断尾部元素.在JS中,由于数组其实就是对象,因此可以使用delete运算符可以从数组中移除元素 var ...

  8. Codeforces Round #369 (Div. 2)E

    ZS and The Birthday Paradox 题目:一年有2^n天,有k个人,他们的生日有冲突的概率是多少?答案用最简分数表示,分子分母对1e6+3取模.1 ≤ n ≤ 10^18, 2 ≤ ...

  9. MySQL设置外键报错 #1452 - Cannot add or update a child row: a foreign key constraint fails 解决方法

    MySQL数据库,当我尝试在A表中设置B表的主键为外键时,报出错误:#1452 - Cannot add or update a child row: a foreign key constraint ...

  10. ASP.NET MVC5实现芒果分销后台管理系统(二):Code First快速集成EntityFramework

    在上一篇文章中,我们已经搭建了整个芒果后台管理系统整个工程架构,并集成了AutoMapper,日志组件等,接下来我们将使用Entity Framework完善系统的持久化存储部分.这篇EF的构造,我将 ...