介绍

介绍

  我们通常会根据不同的需求来创建不同的应用程序。但是对于一些通用相似的结构总是一遍又一遍的实现,至少在某种程度上是这样的。常见的通用模块如授权、验证、异常处理、日志、本地化、数据库连接管理、设置管理、审计日志。同时,我们也在使用如分层、模块化架构,领域驱动设计,依赖注入等创建架构和最佳实践。并且尝试着基于约定俗成的原则开发应用程序。

  因为开发这些框架是非常耗时的,并且很难单独对每个工程创建,所以很多公司创建了私有的框架。使用这些私有框架,他们开发新的应用程序快速且几乎没有bug。当然,并不是所有的公司都那么幸运。大多数的公司没有时间、预算和团队开发私有框架。即使公司有能力创建这样的框架也很难编写文档、培训开发者并且经常维护。

  ASP.NET Boilerplate(ABP)是开源且文档友好的应用程序框架,立意于为所有的公司和开发者开发一个通用的框架。ABP不仅仅是一个框架,同时基于领域驱动和最佳实践提供了强大的架构模型。

快速示例

我们来通过一个简单的类来看下APB的好处:

public class TaskAppService : ApplicationService, ITaskAppService
{
private readonly IRepository<Task> _taskRepository; public TaskAppService(IRepository<Task> taskRepository)
{
_taskRepository = taskRepository;
} [AbpAuthorize(MyPermissions.UpdatingTasks)]
public async Task UpdateTask(UpdateTaskInput input)
{
Logger.Info("Updating a task for input: " + input); var task = await _taskRepository.FirstOrDefaultAsync(input.TaskId);
if (task == null)
{
throw new UserFriendlyException(L("CouldNotFoundTheTaskMessage"));
} input.MapTo(task);
}
}

  这里我们看到了一个应用服务方法。在领域驱动设计中,展示层直接使用应用服务来执行应用用例。我们可以认为UpdateTask方法是Javascript通过AJAX调用的。让我们看下ABP的好处:

  • 依赖注入:ABP使用并提供了一个强大、常规的DI基础设施。因为这个类是一个应用服务,所以应该以transient(每次请求的时候创建)的形式注册到DI容器中。可以简单注入所有的依赖(如在本例中的IRepository<Task>)。
  • 仓库:ABP为每个实体(如本例中的IRepository<Task>)创建一个默认的仓库。默认仓库有许多有用的方法如在本例中使用的FirstOrDefault。我们可以基于我们的需求很方便的库扩展默认仓库。仓库提取DBMS、ORMs并且简化数据访问逻辑。
  • 授权:ABP可以检查权限。如果当前用户没有“updating task”权限或者没有登录的话,ABP会禁止访问UpdateTask方法。ABP使用声明特性简化了授权,但是还有其他的授权方式。
  • 验证:ABP会自动检测输入是否为null。ABP会基于标准数据注解特性和自定义规则验证输入的所有属性。如果请求无效,ABP会抛出恰当的验证异常。
  • 审计日志:对于每一次请求,ABP会根据约定、配置将用户、浏览器、IP地址、调用服务、方法、参数、调用时间、执行时长和其他信息自动保存下来。
  • 工作单元:在ABP中,每一个应用服务方法默认为一个工作单元。ABP会自动创建连接并且在方法开始执行的时候创建事务。如果方法执行完成,没有发生异常,事务就会提交,释放连接。即使方法中使用了不同的仓库或者方法,所有的操作都是原子的(事务处理的)。所有对实体的更改都会随着事务的提交自动保存。因此,我们不需要调用_repository.Update(task)方法。
  • 异常处理:在网络应用中使用ABP我们不需要处理任何异常。所有的异常默认都会被自动处理。如果发生了异常,ABP会自动记录并且返回一个恰当的结果到客户端。例如,如果一个AJAX请求发生了异常,ABP会返回一个JSON到客户端,表明发生了错误。如果想从客户端隐藏真正的异常,除非在后台使用用户友好的异常,如本例中使用的那样。用户友好错误异常在客户端处理,可以使用合适的信息提示给用户。
  • 日志:如你所见,我们可以使用基类中的Logger对象记录日志。默认使用Log4Net,可以通过更改或配置使用其他类库。
  • 本地化:注意到当抛出异常的时候,我们使用了L方法。因此ABP会基于当前用户的文化自动本地化。当然,我们在某些地方定义了CouldNotFoundTheTaskMessage(更多信息可以去本地化文档http://www.aspnetboilerplate.com/Pages/Documents/Localization查看)。
  • 自动映射:在本例的最后一行我们使用了ABP的MapTo扩展方法把输入属性映射到了实体属性。ABP使用AutoMapper类库执行映射。因此,只要对象的属性命名是基于命名规则的,我们就可以很容易,从一个对象得属性映射到另一个对象的属性。
  • 动态WebAPI层:TaskAppService实际上是一个非常简单的类(甚至不需要从ApplicationService传输)。我们通常会封装一个Web API控制器向Javascript客户端提供方法,ABP会在运行时自动帮我们完成这些操作。因此,我们可以直接在客户端调用应用服务方法。
  • 动态JavaScript AJAX代理:ABP会创建JavaScript代理方法,这些方法使我们在客户端调用应用服务方法就像调用JavaScript方法那么简单。

  通过这么简单的一个例子我们看到了ABP的好处。这些所有的工作正常来讲会耗费大量的时间来完成,但是在ABP中这些都被自动处理了。

还有什么

  除了这个简单的例子,ABP提供了强大的基础设施和应用模型。下面ABP的其他一些特征:

  • 模块化:提供了强大的基础设施创建可服用的模块。
  • 数据过滤器:提供了自动数据过滤来实现像软删除、多租户这样的模式。
  • 多租户:ABP完全支持多租户,包括单数据库或每个租户一个数据库的架构。
  • 配置管理:提供强大的基础设施获取或更改应用、租户和用户级别的配置。
  • 单元集成测试:ABP天生是易测试的。ABP提供了基类简化单元集成测试。可以查看这篇文档(https://www.codeproject.com/articles/871786/unit-testing-in-csharp-using-xunit-entity-framewor)获取更多信息。

  要查看ABP所有的特征,查看此文档。(http://www.aspnetboilerplate.com/Pages/Documents

启动模板

  开始一个工程,创建分层,安装nuget包,创建简单布局和菜单等等,所有这些操作是非常耗时的工作。

  ABP提供了预先创建好的启动模板,这样开始一个新工程就简单多了。模板支持SPA(单页面应用)和MPA(多页面应用)架构,同时允许用户使用不同的ORM。

怎样使用

  ABP使用GitHub做源代码管理,同时也发布到Nuget上了。最简单的开始使用ABP的方式就是创建一个启动模板然后跟着文档(http://www.aspnetboilerplate.com/Pages/Documents)来学习。

返回主目录

ABP官方文档翻译 1.1 介绍的更多相关文章

  1. 0.0 ABP官方文档翻译目录

    一直想学习ABP,但囿于工作比较忙,没有合适的契机,当然最重要的还是自己懒.不知不觉从毕业到参加工作七年了,没留下点儿什么,总感觉很遗憾,所以今天终于卯足劲鼓起勇气开始写博客.有些事能做的很好,但要跟 ...

  2. ABP官方文档翻译 2.5 设置管理

    设置管理 介绍 关于 ISettingStore 定义设置 设置范围 重写设置定义 获取设置值 服务端 客户端 更改设置 关于缓存 介绍 每个应用都需要存储设置,并且在应用的某些地方需要使用这些设置. ...

  3. ABP官方文档翻译 10.1 ABP Nuget包

    ABP Nuget包 Packages Abp Abp.AspNetCore Abp.Web.Common Abp.Web Abp.Web.Mvc Abp.Web.Api Abp.Web.Api.OD ...

  4. ABP官方文档翻译 9.2 Entity Framework Core

    Entity Framework Core 介绍 DbContext 配置 在Startup类中 在模块PreInitialize方法中 仓储 默认仓储 自定义仓储 应用程序特定基础仓储类 自定义仓储 ...

  5. ABP官方文档翻译 8.2 SignalR集成

    SignalR集成 介绍 安装 服务器端 客户端 建立连接 內建特征 通知 在线客户端 PascalCase与CamelCase对比 你的SignalR代码 介绍 ABP中的Abp.Web.Signa ...

  6. ABP官方文档翻译 8.1 通知系统

    通知系统 介绍 发送模型 通知类型 通知数据 通知严重性 关于通知持久化 订阅通知 发布通知 用户通知管理 实时通知 客户端 通知存储 通知定义 介绍 在系统中通知用来基于特定的事件告知用户.ABP提 ...

  7. ABP官方文档翻译 7.3 Quartz集成

    Quartz集成 介绍 安装 创建Jobs 计划安排Jobs 更多 介绍 Quartz是一个全功能的.开源的job计划安排系统,可以用在小的apps也可以用于大型的企业系统.Abp.Quartz包简化 ...

  8. ABP官方文档翻译 7.2 Hangfire集成

    Hangfire集成 介绍 ASP.NET Core集成 ASP.NET MVC 5.x集成 面板授权 介绍 Hangfire是一个综合的后台job管理器.你可以 把它集成到ABP,用来取代默认的后台 ...

  9. ABP官方文档翻译 7.1 后台Jobs和Workers

    后台Jobs和Workers 介绍 后台Jobs 关于Job持久化 创建后台Job 在队列中添加一个新Job 默认的后台Job管理器 后台Job存储 配置 禁用Job执行 异常处理 Hangfire集 ...

随机推荐

  1. FragmentStatePagerAdapter写法

    为了节省资源,分批加载数据//适配器class TabLayoutViewPagerAdapter extends FragmentStatePagerAdapter { public TabLayo ...

  2. Android 蓝牙学习

    Android 蓝牙学习 学习缘由 上个礼拜公司要开发个简单的五子棋游戏!其中一个需求就是支持蓝牙对战!所以苦逼的我学习蓝牙方面的知识了! 简介 Bluetooth是目前使用最广泛的无线通讯协议,近距 ...

  3. 【黑金原创教程】【TimeQuest】【第七章】供源时钟与其他

    声明:本文为黑金动力社区(http://www.heijin.org)原创教程,如需转载请注明出处,谢谢! 黑金动力社区2013年原创教程连载计划: http://www.cnblogs.com/al ...

  4. 微信登陆,微信SDK授权登陆经验分享

    From:http://www.eoeandroid.com/thread-547012-1-1.html 最近因为项目需要做了微信登陆,好像也是微信最近才放出来的接口.还需要申请才能有权限实现授权. ...

  5. 160509、Java过滤器与SpringMVC拦截器之间的关系与区别

    今天学习和认识了一下,过滤器和SpringMVC的拦截器的区别,学到了不少的东西,以前一直以为拦截器就是过滤器实现的,现在想想还真是一种错误啊,而且看的比较粗浅,没有一个全局而又细致的认识,由于已至深 ...

  6. SaltStack之编译安装LNMP环境

    使用saltstack编译安装LNMP环境 一,系统版本查看 二,安装salt-master和salt-minion 安装配置过程参考SaltStack概述及安装 三,修改配置文件 /etc/salt ...

  7. img元素的alt和title的区别?

    alt是图片加载失败时显示在网页上的提示信息: title是鼠标放上面时显示的文字(图片加载失败鼠标放显示的代替文字上时仍然会显示提示信息): 除此之外,alt是img的必要属性,只能用在img.ar ...

  8. 对于应用需要记录某个方法耗时的场景,必须使用clock_gettime传入CLOCK_MONOTONIC参数,该参数获得的是自系统开机起单调递增的纳秒级别精度时钟,相比gettimeofday精度提高不少,并且不受NTP等外部服务影响,能准确更准确来统计耗时(java中对应的是System.nanoTime),也就是说所有使用gettimeofday来统计耗时(java中是System.curre

    对于应用需要记录某个方法耗时的场景,必须使用clock_gettime传入CLOCK_MONOTONIC参数,该参数获得的是自系统开机起单调递增的纳秒级别精度时钟,相比gettimeofday精度提高 ...

  9. FW:主流RPC框架

    主流RPC框架  2015年10月27日  zman  RPC 介绍目前在互联网公司比较流行的开源的RPC框架. RPC框架比较   语言 协议 ​服务治理 ​社区 机构 Hessian 多语言 he ...

  10. python基础-第七篇-7.4异常处理

    异常基础: 异常处理首先要捕获异常,不让程序中断,也不让错误信息直接呈现出来,然后就是你该怎么处理异常,以什么方式显示 try: pass except Exception,ex: pass 在需要用 ...