ABP框架模板开发手册.docx

上传人:小** 文档编号:13542329 上传时间:2020-06-20 格式:DOCX 页数:30 大小:1.22MB
收藏 版权申诉 举报 下载
ABP框架模板开发手册.docx_第1页
第1页 / 共30页
ABP框架模板开发手册.docx_第2页
第2页 / 共30页
ABP框架模板开发手册.docx_第3页
第3页 / 共30页
资源描述:

《ABP框架模板开发手册.docx》由会员分享,可在线阅读,更多相关《ABP框架模板开发手册.docx(30页珍藏版)》请在装配图网上搜索。

1、ABP框架模板开发手册杭州蒙特信息技术有限公司2018年1月目录1ABP框架介绍31.1ABP简介31.2ABP多层结构31.3ABP环境51.4开发环境52搭建网站52.1获取源码52.2搭建数据库62.3搭建站点83模块开发93.1领域层93.2应用层184后台页面185前台页面186后台配置181 ABP框架介绍1.1 ABP简介我们总是对不同的需求开发不同的应用。但至少在某些层面上,一次又一次地重复实现通用的和类似的功能。如:授权,验证,异常处理,日志,本地化,数据库连接管理,设置管理,审核日志等功能。所以我们创建架构和最佳实践,如分层和模块架构,DDD,依赖注入等,并尝试开发应用时基

2、于一些约定。由于所有这些是非常耗时而且很难单独创建并可适用于每个项目,许多公司创建自己的框架,他们用自己的框架能快速开发新应用而且不出错。但不是所有的公司都是幸运的,大部分公司没有时间,预算和团队来开发好的框架。他们甚至都没有可能创建一个框架,因为编写文档,培训开发人员和维护框架都是非常困难的。 Boilerplate (ABP)是一个开源并且有丰富文档的应用框架,开发宗旨是:“为所有公司,所有开发人员,开发出一个通用框架!”,而且不只是一个框架,同时提供一个强大的基于DDD的构架模型和最佳实践。1.2 ABP多层结构一个应用的代码库的分层是一个广为接受的技术,用来减少复杂度和提高代码复用性。

3、ABP依照DDD理念来分层,在DDD里有4个基本的层: 表示层:为用户提供一个界面。使用应用层来完成用户交互。 应用层:表示层与领域层的媒介。协调服务业对象执行指定的应用任务。 领域层:包含业务对象和业务规则。是整个应用的核心。 基础层:提供支持更高层的通用技术。一个基础层的典型例子是通过ORM框架实现与数据库的交互的仓储,或是实现发送邮件的邮件供应器。也可以根据需要添加层,例如: 分布服务层:为远程客户端公开应用特性。像 web API和WCF等。这些都是以领域为核心的架构的通用层。实现上可能有些细微的差别。层和结构的预览如下LayersPresentationView Models (Ja

4、vascript), Views (HTML/CSS), Localization,Navigation,NotificationsWebWeb API Controllers, MVC Controllers, OData, CoreApplicationApplicationServices,DTOs,DTOMappers,Authorization,Session,Audit LoggingDomain (Core)Entities, Value Objects,Repositories,Domain Services,Unit of Work,Domain EventsInfrastr

5、uctureORM (EntityFramework,NHibernate),DB Migrations,Background JobsOthers (common)ABP分层结构图如下1.3 ABP环境前台环境 MVC + Bootstrap后台环境Angular框架 + AdminLTE + Bootstrap基础环境.NET Framework 4.6.1 + EF1.4 开发环境TypeScript:微软开发的自由和开源的编程语言,这是Javascript的超集;Web Compiler: A Visual Studio extension that compiles LESS, Sa

6、ss, JSX, ES6 and CoffeeScript files;如何ABP的.NET框架是Core 2.0时则需要使用Visual Studio 20172 搭建网站22.1 获取源码第一步:通过SVN获取源码,源码下载之后Visual Studio打开源文件,第二步:用Visual Studio还原NuGet包如下图第三步:重新生成解决方案(检测项目正确性和完整性);2.2 搭建数据库122.12.22.2.1 配置信息第一步:创建空数据库database:database(数据库);uid:uid(用户名);pwd:ILwFjPFH8J(密码);第二步:修改配置文件g,配置网站数据

7、库信息,更改ConnectionStrings的数据库连接字符串信息;database:数据库名 ,uid:用户名,pwd:密码; 配置方法如下图2.2.2 创建数据库第一步:打开程序包管理器控制台第二步:选择EntityFramework项目第三步:将Web项目设置为启动项第四步:执行命令创建数据库及表:Update-DatabaseVerbose第五步:执行完打开数据库管理器查看,如下图所示说明成功了到这里数据库的搭建工作完成。2.3 搭建站点第一步:重新生成解决方案第二步:将Mt.文件夹内的所有文件拷贝至网站的根目录下第三步:访问网站;后台网址:域名/B;默认账号:admin,密码:12

8、3qwe;开发者账号:mountor,密码:123qwe后台页面3 模块开发33.1 领域层领域层必须实现所有业务规则。实体:展示数据和领域业务的操作。通常地它们映射到数据库表。仓储:类似于对象集合,用来获取和持久化实体到数据源(数据库)。领域层定义了仓储,但不实现它们,由基础层来实现它们。领域事件:定义领域里特定的事件,并触发和处理它们。领域服务利用实体(及其它领域对象)实现那些不属于某个单独实体的业务规则。工作单元:是一个管理数据库连接和事务的设计模式,跟踪实体变化并保存变化到数据存储。领域层定义了它,但由基础层实现它。这一层应该尽可能地独立于第三方类库。33.13.1.1 实体类实体是D

9、DD一个核心的概念。Eric Evans是这么描述的:“一个对象根本上不是按它的特性定义的,而是按一个线程的连续性和身份来定义”。所以实体有一个id属性存入数据库中。一个实体通常映射成关系型数据库的一个表。继承FullAuditedEntity:主键类型为Guid类型的全审计实体(软删除,记录删除时间和删除人员等信息)(必要)IPassivabile:信息状态接口(必要)IMustHaveTenant:必要性租户字段接口(必要)IMenuID:栏目ID接口(必要)INeedAuxiliaryId:辅助ID接口(辅助ID为long类字段)(必要)ILanguage:语言接口(必要)IAutoSy

10、nchronous:数据同步接口(非必要)ISynchronousSource:数据同步源接口(非必要)常量:字段长度限制规范:定义字段的限制3.1.2 领域服务领域服务(或服务)用来执行领域操作和业务规则。Eric Evans描述一个好的服务需要三个特点(在他的DDD书里): 操作与领域概念(不是一个实体或值对象天生的一部分)相关。 接口要按照领域模型的其它元素来定义。 操作是无状态的。与应用服务获取/返回DTO(数据传输对象)不同,领域服务获取/返回领域对象(如实体或值类型)。领域服务可被应用服务或其它领域服务调用,但不直接被展现层(应用服务是针对它的)使用。首先我们要为服务定义一个接口,

11、接口继承IDomainService,接口中的服务包含创建、修改和删除有五个方法。其次实现服务IDomainService 接口和DomainService 服务ABP定义了IDomainService接口,按约定所有的领域服务都要实现它,实现之后,领域服务被自动暂时的注册到依赖注入系统。同样,领域服务(随意地)可以从DomainService类继承,因此它可以使用继承得来的日志、本地化、等属性。即使不继承DomainService类,也可以在需要时注入它。3.1.3 定义模块权限授权系统使用IPermissionChecker来检查许可,虽然你用自己的方式实现它,不过在module-zero

12、项目里已完全实现。如果没有实现该接口,会使用NullPermissionChecker,它给每个人授予所有许可。为每个操作定义的唯一许可必须得到授权,为使用许可要先定义一个,ABP是按模块化设计的,所以不同的模块可以拥有不同的许可,一个模块为了定义它的许可,应当创建一个继承AuthorizationProvider的类。授权供应器示例如下:第一步:定义权限常量:第二步:定义权限许可第三步:定义许可中displayName的本地化(/Core/Localization/AppPermissions)IPermissionDefinitionContext拥有获取和创建许可的方法。一个许可包含一些

13、属性:Name:一个系统域内的唯一名称,用一个字符串常量,不用可变的字符串,是一个好的做法。在分级里我们更喜欢用.(点)号来命名,但它不是必须的,你设置为你喜欢的名称,唯一的规则是一定要唯一。DisplayName:一个本地化的用来之后在UI上显示许可的文本。Description:一个本地化的用来之后在UI上显示许可描述的文本。MultiTenancySides:在多租户应用里,许可可被租户或宿主使用,这是一个标记性的枚举,所以一个许可可同时被租户和宿主使用。DependedFeature:用来表明一个对Feature(特色)的依赖,所以这个许可只有在满足Feature(特色)依赖时才会被允

14、许。一个许可可以有一个父许可和多个子许可,虽然这对于许可检查没有什么作用,但可能有助于在UI上组织许可。第四步:创建一个授权供应器之后,我们应当在我们模块的预初始化方法里注册它,在Core/Common/中注册许可:3.1.4 定义模块功能功能系统使用IFeatureValueStore来获取功能的值。尽管你可以用自己的方式实现它,但在module-zero项目里已经完全实现。如果它没有被实现,NullFeatureValueStore用来为所有功能返回null(这种情况下使用默认功能值)。功能的值类型Boolean 类型:可以是“true”或“false”,一个这种类型的功能可以是启用或禁用

15、(为一个版本或一个租户)。Value 类型:可以是任意值,它保存和获取一个字符串,数字也保存成字符串。第一步:定义功能常量:第二步:定义常量:在检查功能前,先要定义它,一个模块可通过继承FeatureProvider类来定义自己的功能一个功能定义要求至少两个属性:Name:一个唯一名称(字符串),这个功能的标志。DefaultValue:一个默认值,当我们需要这个功能的值而又不能从当前租户取得时,我们需要一个默认值。DisplayName:一个本地化的字符串,为用户显示这个功能的名称。第三步:定义功能的displayName的本地化(/Core/Localization/ AppFeature

16、s)第四步:在创建一个功能供应器之后,我们应当在我们模块()的PreInitialize方法里注册它(Core/Common/),如下所示:3.1.5 更新数据库第一步:定义DbSet(Mt.)第二步:定义表名(Mt.yFramework. HkWebDbModelBuilderExtensions)第三步:执行命令更新数据库打开工具-NuGet包管理器-程序包管理器控制台,重新生成解决方案;然后将默认项目设置为EntityFrameworkCore;最后在控制台中输入Add-Migration“name”(name:不能用重复的名字可以使用“描述+日期”如:createNews) 运行之后M

17、igrations文件夹中2070_生成;第四步:更新数据库创建表;在程序包管理器控制台中运行Update-Database命令随后数据库就会新建了一个表3.2 应用层应用层包含用于展示层的应用服务。一个应用服务方法可以接收一个DTO(数据传输对象)作为输入,使用这个输入执行一些领域层的操作,并在需要时返回另一个DTO。它不应该接收或返回实体。一个应用服务方法被认为是一个工作单元。用户输入验证也是在这一层实现。建议使用类似于AutoMapper库等工具来映射实体和DTO。这层还包含当前用户信息的会话(Session)。3.23.2.1 DTOData Transfer Objects(DTO)

18、用来在应用层和展现层之间传输数据。展现层使用一个DTO调用一个应用服务方法,然后应用服务使用服务对象执行一些特定业务逻辑,并返回一个DTO给展现层。因此,展现层是完全独立于领域层的。在一个理想的分层应用里,展现层不直接使用领域对象(仓储、实体.)。DTO的必要性:首先为每个应用服务方法创建一个DTO看起来是件乏味且费时的工作,但如果你正确使用它,它能解救你的应用。为什么呢?领域层的抽象:dto提供一个有效的方法从展现层抽象领域对象,因此,你的层正确分离开,即使你想完全地改变展现层,也可以继续使用已存在的应用层和领域层。相反,你可以重写你的领域层、完全改变数据库结构、实体和ORM框架,只要你的应

19、用服务契约(方法签名和DTO)保持不变,展现层也不用做任何修改。数据隐藏:考虑一下:你有一个User实体,它有Id、Name、EmailAddress和Password属性,如果UserAppService的GetAllUsers()方法返回一个List,任何人都可以看到所有用户的密码,即使你没有在屏幕上显示它,也是不安全的。不只是数据安全,还有就是数据的隐藏,应用服务应该只向展现层返回必要的数据,不多也不少。序列化和延迟加载问题:当你返回一个数据(一个对象)给展现层时,它可能会在某处被序列化,例如:在一个返回Json的MVC方法里,你的对象会被序列化成JSON,然后发送给客户端,在这种情况下

20、,如果返回一个实体给展示层可能会有问题,为什么呢?在一个真实的应用里,你的实体间可能存在相互引用,User实体可能关联到Roles(多个角色),所以如果你想序列化User,那么它的Roles也要被序列化,而Role类可能包含一个List,Permission类可能又关联到PermissionGroup类等等。你应该能明白序列化这些对象,可能就意外的序列化了整个数据库,而如果你的对象存在循环引用,它就无法完成序列化了。怎么解决呢?把属性标记为NonSerialized(不序列化)?不,你不知道它何时应当被序列化又何时不应当被序列化,可能在这个应用服务里要序列化,而在另一个服务里不要序列化,所以返

21、回一个安全地可序列化的,经过特别设计的DTO是一个好的选择。另一方面,几乎所有ORM框架都支持延迟加载,它是一个只在需要时从数据库加载实体的特性。假设User类有一个指向Role类的引用,当你从数据库获取一个User时,Role属性没有被填充,当你第一次读取Role属性时,它再从数据库中加载。所以你返回这么一个实体给展现层,它将去数据库获取额外的实体。如果一个序列化工具读取这个实体,它递归读取所有属性,可能又会序列化你整个数据库(如果实体间恰好存在一定的关系)。当然我们可以说出在展现层使用实体的更多问题,所以最好的做法是在应用层里不引用包含领域(业务)层的程序集。DTO 约定和验证:ABP强支

22、持DTO,它提供了一些约定类和接口,并建议了一些命名和使用约定,当你如本节描述的这样去写代码,ABP会自动完成一些任务。第一步:在Appliction层定义模块对应的文件夹并区分前后台Members:会员模块文件夹;BackEnd:会员模块后台应用层文件夹FrontEnd:会员模块前台应用层文件夹Dto:展示层交互用到的数据传输对象文件夹第二步:定义DTO,根据展示层交互具体功能定义各自的DTO;ABP建议命名输入/输出参数为:MethodNameInput和MethodNameOutput,并为每个应用服务方法定义单独的输入和输入DTO。即使你的方法只接受/返回一个参数,也最好是创建一个DT

23、O类,因为你的代码将来可能需要扩展,你可以稍后添加更多属性,而不必修改你方法的签名也不用打断你已存在的客户端应用。public class DeleteMemberInput Required public IList DeleteList get; set; public class SearchPeopleInput StringLength(40, MinimumLength = 1) public string SearchedName get; set; AutoMap(typeof(Person) /定义双向映射public class PersonDto : EntityDto

24、public string Name get; set; public string EmailAddress get; set; 在方法开始运行前,ABP会自动验证输入,这类似于 Mvc的验证,但请注意:应用服务不是一个控制器,它就是一个单纯的C#类,ABP拦截它并自动检查输入。有很多的验证,请查阅DTO 验证文档。3.2.2 应用服务应用服务把领域逻辑暴露给展现层。一个应用服务被展现层使用一个DTO(数据传输对象)参数所调用,使用领域对象执行一些特殊业务逻辑并返回一个DTO给展现层。因此,展现层是完全独立于领域层,在一个理想的分层应用里,展现层从不直接使用领域对象。IApplication

25、Service接口:在ABP里,一个应用服务应当实现IApplicationService接口,为每个应用服务创建一个接口是好的做法,所以我们先为一个应用服务创建一个接口;IBackEndAppService、IFrontEndAppService继承了IApplicationService,分别对应后台应用服务接口、前台应用服务接口第一步:定义服务接口第二步:实现服务接口,应用服务继承ApplicationService(后台应用服务继承HkWebAppServiceBase(HkWebAppServiceBase继承了ApplicationService);前台应用服务继承Applicat

26、ionService)和定义的服务接口;注入模块的领域层服务。第三步:应用服务方法的功能和权限定义4 后台页面44.1 页面开发后台开发位置:Mt./Mt/tenant/views开发环境:+Bootstrap44.14.1.1 页面开发字段描述备注.对应的页面名$scope作用域$state$stateParams参数集selectionCheck多选框指令服务$uibModal模态框指令uiGridConstantsgrid指令.info后台应用服务接口draggalbeRowsHelper行拖动指令/ 权限 vm.permissions = create: .hasPermission(

27、Pages_Manage_Info_Create), update: .hasPermission(Pages_Manage_Info_Update), deleted: .hasPermission(Pages_Manage_Info_Delete), query: .hasPermission(Pages_Manage_Info_Query), sortChange: .hasPermission(Pages_Manage_Info_Sort), stateChange: .hasPermission(Pages_Manage_Info_Publish) ;权限使用方式如下,页面中数据的绑

28、定事件调用4.1.2 配置路由在Mt./Mt/中设置路由映射;字段描述备注info路由名,用作后台模块配置时使用Url路由链接templateUrl链接对应的页面模板(文件的全路径)4.2 后台配置4.24.2.1 配置模块字段描述备注名字模块名称必填链接路由映射的名必填图标模块显示的图标Bootstrap图标打开方式空值、_blank选填描述模块描述排序模块排序是否发布模块状态位是/否4.2.2 功能设置配置模块对应的模块功能4.2.3 栏目配置5 前台页面55.1 Mvc控制器ABP通过nuget包.Mvc集成到 Mvc 控制器。你可以像往常那样创建普通的Mvc控制器,依赖注入可以对普通的

29、Mvc控制器起作用,但你应当使你的控制继承自AbpController,它提供了许多好处和更好的集成到ABP。Controller继承HkWebControllerBase(HkWebControllerBase继承AbpController并添加了MyUrlHelper、ITenancyNameFinder并重写了Initialize、RedirectToAction、RedirectToActionPermanent、OnException等)5.2 Mvc视图字段描述备注Layout页布局页Partial页部分页RenderBody呈现子页的主体内容RenderSection呈现定义的部分RenderSection(string name, bool required = true);required默认为true必须覆写设为false则为可选覆写;rScript文件引用r(virtualPath,virtualPath1 ,.)rCSS文件引用r(virtualPath,virtualPath1 ,.)n生成a标签链接n(视图,控制器)布局页_l头部布局页_l

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!