.Net 6.0 发布之后,ABP Framework 也在第一时间进行了升级,并在一个多星期后(2021-11-16)发布了 5.0 RC.1 ,新功能和重要变更基本已经确定。
5.0版本新特性
新特性列表:
- 静态 C# 和 JavaScript 客户端代理 【重要特性】
- 分布式事件总线支持事务收件箱&发件箱模式 【重要特性】
- 在事务中发布事件
- 禁用用户
- 租户邮箱设置
- 仪表板授权控制
- AbpControllerBase 基类
- 自动设置新实体 TenantId 属性值
静态(生成) C# 和 JavaScript 客户端代理
动态 C# 和 JavaScript 客户端代理是ABP框架最受欢迎的特性之一。动态代理在运行时生成代理代码,并使客户端到服务端的调用变得简单。在 ABP Framework 5.0 中,提供了另一种方法:可以在开发时生成客户端代理代码。
静态代理的优点:
- 性能提升,因为不需要在运行时获取 HTTP API 定义信息。
- 项目解耦,以微服务架构为例,API 网关应用直接使用静态代理,所以不需要在项目中添加对应的微服务 HTTP API 层的引用。动态代理方式,需要先从 API 网关返回一个 HTTP API 定义组合,所以需要在网关添加微服务 HTTP API层的引用。
静态代理的缺点:当 API 终结点定义发生改变时,需要重新生成客户端代理代码。
至于使用哪种代理方式,需要结合项目实际情况进行选择。是的,软件开发中没有“完美技术”,总是需要权衡利弊,适合才是最好的。
分布式事件总线支持事务收件箱&发件箱模式
这应该是分布式系统开发人员最期待的特性之一。(至此,使用 ABP Framework 开发分布式系统的基础设施已经完备!)
事务发件箱模式用于在操作应用程序数据库的同一个事务中发布分布式事件。
当数据发生变化时,分布式事件被保存在同一个事务中的数据库中,然后由一个独立的后台工作进程发送给消息代理,如RabbitMQ或Kafka,支持失败重试机制。通过这种方式,确保数据库状态和已发布事件之间的一致性。
事务收件箱模式,确保数据库状态和已接收事务之间的一致性。首先将接收的事件保存到数据库,然后在事务中执行事件处理程序同时从收件箱队列中移除事件。通过将处理过的消息保留一段时间,并丢弃从消息代理接收到的重复事件,确保事件只执行一次。
在应用程序中,启用收件箱和发件箱模式需要一些手动步骤。可以参看控制台应用程序示例。
在事务中发布事件
前面介绍的特性(发件箱和收件箱模式)解决分布式系统事务发布事件问题。事务中发布事件这一功能,解决在非分布式应用程序发布事件的同一事务中执行事件处理程序的问题。在 5.0 中,所有事件(本地或分布式)在相同事务中处理。任何处理程序执行失败,该事务都会回滚。如果不希望触发回滚,可以使用 try/catch
捕获并忽略事件处理程序中的异常。
有一点需要清楚的是如果系统中并没有集成分布式事件提供程序,如 RabbitMQ 、Kafka,那么分布式事件总线将在进程内执行,此时就像本地事件一样。因此,无论系统是分布式或非分布式,所有事件都变成事务性的。
以上处理都是默认进行的。有一个与此更改相关的弃用说明(一些预定义的事件将在下一个主版本中删除,已经不再需要了)。
禁用用户
Identity 应用模块新增禁用/启用用户功能,对应添加和编辑用户对话框中 Active 复选框,禁用操作实现禁止用户登陆系统而不删除用户数据。
这项功能在AbpUsers
表中添加新字段,所以需要添加新的数据迁移。
租户邮箱设置
如果是创建多租户应用,现在支持为每个租户单独进行邮件发送设置。为了使设置可用,首先需要为租户设置对应功能权限:
勾选租户邮件设置权限:
在开发环境,登出,切换到租户并使用租户管理员登陆,点击 Administration -> Settings 菜单,可以看到邮件设置:
仪表板授权控制
ABP可以集成 Hangfire 作为后台作业工作者,Hangfire 仪表板用于监控和控制后台作业队列,参看仪表板截图:
Hangfire仪表板默认无需授权即可访问,任何用户可通过 /hangfire
URL查看和控制作业。在 ABP 5.0 版本中,为Hangfire 仪表板添加内置授权过滤器AbpHangfireAuthorizationFilter
。使用如下示例代码代替 app.UseHangfireDashboard();
实现:
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter() }
});
添加过滤器之后,只有授权用户能够查看仪表板,当然,建议设置一个权限名称,只有拥有该权限的用户可以查看仪表板:
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
AsyncAuthorization = new[] {
new AbpHangfireAuthorizationFilter("MyPermissionName")
}
});
上面示例将Hangfire 仪表板权限定义名为 MyPermissionName
,使用框架权限系统。
AbpControllerBase 基类
ABP 提供 AbpController
类作为 MVC 控制器的继承基类,在控制器中通过依赖注入提供常用的服务,以此简化控制器的编写。在 5.0 版本中,提供第二个控制器基类 AbpControllerBase
,不包含视图功能,用于创建 API 控制器。在开发 API 控制器,建议使用 AbpControllerBase
代替 AbpController
类。
示例:创建 API 控制器
[Route("api/products")]
public class ProductController : AbpControllerBase
{
// TODO: ...
}
自动设置新实体 TenantId 属性值
在 5.0 版本中,当你创建一个新实体对象(实现 IMultiTenant
接口)时,ABP 在 Entity
基类构造函数中自动设置 TenantId
,所有实体和聚合根基类都继承 Entity
类。TenantId
设置为当前租户 ICurrentTenant.Id
属性值。
之前,由开发者为新实体设置 TenantId
值,现在交给 ABP 自动处理,仅在需要设置为其他租户Id时手动设置。
在极少数情况下,需要注意这个变更,比如:从一个租户上下文创建 host 端实体,不需要明确地设置 host 实体 TenantId
属性为 null
。
主要变更说明
- 升级到
.Net 6.0
- 升级到
Bootstrap 5
IRepository
不再继承IQueryable
接口- MVC / Razor Pages UI 移除对 gulp 打包依赖,使用
abp-install-libs
代替。 - 弃用
EntityCreatingEventData
,EntityUpdatingEventData
,EntityDeletingEventData
和EntityChangingEventData
。
dotNET兄弟会-公众号
专注.Net开源技术及跨平台开发!致力于构建完善的.Net开放技术文库!为.Net爱好者提供学习交流家园!