ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称。
ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序基础框架和项目模板。
ASP.NET Boilerplate 基于DDD的经典分层架构思想,实现了众多DDD的概念(但没有实现所有DDD的概念)。
ABP框架实现了以下几点特征:
- 多语言/本地化支持
- 多租户支持(每个租户的数据自动隔离,业务模块开发者不需要在保存和查询数时写相应代码)
- 软删除支持(继承相应的基类或实现相应接口,会自动实现软删除)
- 统一的异常处理(应用层几乎不需要处理自己写异常处理代码)
- 数据有效性验证(Asp.NET MVC只能做到Action方法的参数验证,ABP实现了Application层方法的参数有效性验证)
- 日志记录(自动记录程序异常)
- 模块化开发(每个模块有独立的EF DbContext,可单独指定数据库)
- Repository仓储模式(已实现了Entity Framework、NHibernate、MangoDB、内存数据库)
- Unit Of Work工作单元模式(为应用层和仓储层的方法自动实现数据库事务)
- EventBus实现领域事件(Domain Events)
- DLL嵌入资源管理
- 通过Application Services自动创建Web Api层(不需要写ApiController层了)
- 自动创建Javascript 的代理层来更方便使用Web Api
- 封装一些Javascript 函数,更方便地使用ajax、消息框、通知组件、忙状态的遮罩层
因为我也是个abp的初学者所以先简单讲讲我最近学到的一些知识
ABP中的多租户
多租户是指一个软件架构的实力软件运行在一个服务器上,但存在多个租户。租户是一组共享一个公共的用户访问特定权限的软件实例。
默认会话( ClaimsAbpSession)用给定的顺序实现使用不同的方式来找到当前请求相关的租户
对于已登陆的用户,从当前声明中获取租户id,如果在声明中没有发现tenantid,那么该用户被假为host用户。
对于没有登陆的用户,它会尝试分别从三种tenant resolve contributors中解析租户id。
1.DomainTenantResolveContributer:从url中解析租户名通常来说是域名或子域名。在模块的预初始化中可以配置域名格式 比如:Configuration.Modules.AbpWebCommon().MultiTenancy.DomainFormat = "{0}.mydomain.com";)。 会解析{0}.mydomain.com,从而得到租户名为{0}。接下来就会通过ITenantStore查找{0},如果该租户名被发现,那么该租户id就是当前租户的id。
2. HttpHeaderTenantResolveContributer: 如果存在Abp.TenantId请求头,那么会尝试从请求头中解析租户名。
3. HttpCookieTenantResolveContributer: 如果存在Abp.TenantId的cookie值,那么就从该cookie中解析租户名。
三个contributors按顺序运行并由第一个解析成功的contributor获胜,如果三个contributors都没解析道租户名,那么当前请求会被考虑作为host请求。解析器可以添加也可以移除。
Tenant Store 租户商店
DomainTenantResolveContributer 使用 ITenantStore 通过租户名来查找租户ID。NullTenantStore 默认实现了 ITenantStore 接口,但是它不包含任何租户,对于查询仅仅返回null值。当你需要从数据源中查询时,你可以实现并替换它。在 Module Zero 的 Tenant Manager 中已经实现了该扩展。所以,如果你使用了module zero,那么你不需要关心tenant store。
数据过滤器
在从数据库检索entity的时候我们必须添加TenantId过滤当前的租户entity。其中存在两种过滤接口:IMustHaveTenant、IMayHaveTenant
IMustHaveTenant Interface
这个接口通过TenantId属性来区分不同的租户的entity。例:
public class Product : Entity, IMustHaveTenant
{
public int TenantId { get; set; }
public string Name { get; set; }
//...其它属性
}
然后abp会发现这是一个与租户相关的entity,并自动隔离其他租户的entity。
IMayHaveTenant Interface
这是一个租户和host共享的过滤接口、当该TenantId为空的时候意味着这是一个host实体。例:
public class Role : Entity, IMayHaveTenant
{
public int? TenantId { get; set; }
public string RoleName { get; set; }
//...其它属性
}
接下来是在.NET CORE MVC开发过程中很重要的“依赖注入”,很多刚入门的程序员可能也跟我一样听到这个词一头雾水
其实,依赖注入(dependency injection)就跟他的名字一样就是把类与类之间的依赖关系注入到容器之中,从而减少依赖类之中的创建代码,可以更好的对单一单元进行测试和维护
比如 :
public class PersonAppService
{
private IPersonRepository _personRepository;
public PersonAppService()
{
_personRepository = new PersonRepository();//在类之中的new是的类与类之间更加紧密,有了这样的依赖,很难(甚至不可能)对PersonAppService进行单元测试。
}
public void CreatePerson(string name, int age)
{
var person = new Person { Name = name, Age = age };
_personRepository.Insert(person);
}
}
然后加下来是个函数注入的例子:
public class PersonAppService
{
private IPersonRepository _personRepository;
public PersonAppService(IPersonRepository personRepository)
{
_personRepository = personRepository;
}
public void CreatePerson(string name, int age)
{
var person = new Person { Name = name, Age = age };
_personRepository.Insert(person);
}
}
这被称为构造函数注入。现在,PersonAppService不知道哪些类实现IPersonRepository以及如何创建它。谁需要使用PersonAppService,首先创建一个IPersonRepository PersonAppService并将其传递给构造函数