ABP框架
2017-10-27 12:13:32 35 举报
AI智能生成
ABP框架是一种基于.NET Core的开源应用程序框架,由Volo.Abp团队开发。它提供了一种简单、快速、灵活的方法来构建企业级应用程序。ABP框架具有高度模块化和可扩展性,支持多种数据库和UI框架,并提供了一套完整的解决方案,包括认证、授权、API管理、多租户等。 ABP框架的目标是帮助开发人员更快地构建高质量的应用程序,同时减少重复劳动和提高生产力。它提供了许多内置功能和模块,如实体框架、工作流引擎、事件聚合器等,以帮助开发人员更轻松地实现复杂的业务逻辑。此外,ABP框架还提供了丰富的文档和社区支持,帮助开发人员更好地了解和使用该框架。
作者其他创作
大纲/内容
领域层
实体
IEntity
Entity
Id
默认int(int32)
使用泛型自定义 Entity<TPrimaryKey>
==
判断Id是否相等
IsTransient()
检测实体是否有Id属性
IFullAudited
FullAuditedEntity
IAudited
AuditedEntity
ICreationAudited
CreationAuditedEntity
IHasCreationTime
CreationTime
CreatorUserId
IModificationAudited
LastModificationTime
LastModifierUserId
IDeletionAudited
IsDeleted
软删除,数据库中无法检索到
正确说法应该是ABP框架自动过滤掉,数据库中依然存在,但只有EF才自动过滤?
IPassivable
IsActive
激活状态/闲置状态,数据库中可以检索到
仓储
IRepository
定义
IRepository<TEntity>
IRepository<TEntity, TPrimaryKey>
查询
Get
根据Id,找不到会抛错
Single
根据lambda,找不到会抛错
FirstOrDefault
根据lambda,找不到返回null,但只返回第一个
Load
并不会从数据库中检索实体,但它会创建延迟执行所需的代理对象,没有实现则会跟Get一样
GetAllList
可选根据lambda过滤
GetAll
返回IQueryable,之后可Linq(延迟执行直到ToList)
T Query<T>
自定义返回值
新增
Insert
普通新增
InsertAndGetId
返回新增实体Id,适用于自增长
InsertOrUpdate
自动根据Id判断
InsertOrUpdatedAndGetId
更新
Update
更新后返回实体对象本身
删除
Delete
TEntity entity
根据实体对象
TPrimaryKey id
根据实体Id
Expression<Func<TEntity, bool>> predicate
根据lambda
其他
Count
获取数据表中实体的数量(int),可根据条件获取
LongCount
返回值类型Long
异步
框架支持异步,如果没有实现,则与同步效果相同
await
只有在async方法里可以使用
await开启新线程并立刻返回主线程
await之后的代码会封装成委托,异步完成后调用
不会阻塞主线程造成卡顿,但是顺序执行
web 让出当前线程
实现
实现IRepository接口即可
ABP框架使用ORM框架实现
NHibernate
EntityFramework
管理数据库链接
自动化管理
Unit of Work
生命周期
所有的仓储对象都是暂时性的
最佳实践
尽量使用预定义仓储,少用定制仓储
IRepository<T>
实现IRepository<TEntity>
仓储类无状态
当仓储可以使用相根据注入,尽可较少或是不相根据于其它服务
工作单元
通用
Web请求到达时创建连接
需要时创建使用后释放连接
ABP框架
Unit of Work (UoW)
仓储方法 Repository
应用服务 Application service
UnitOfWorkAttribute
[UnitofWork]
使用工作单元
[UnitOfWork(IsDisabled = true)]
禁用
[UnitOfWork(false)]/[UnitOfWork(isTransaction:false)]
无事务
注意,ORM框架(像是NHibernate和EntityFramework)会在单一命令中于内部进行数据储存。假设你更新了一些的实体于非事务的UoW。即便于这个情境下所有的更新都会于单一数据库命令的工作单元尾部完成。但是,如果你直接执行SQL查询,它会立即被执行。
IUnitOfWorkManager
Begin()
Complete()
嵌套
共享一个连接和事务
自动保存
ABP自动存储变化于工作单元方法的末端
IQueryable延迟执行
类似仓储类的GetAll方法,必须启用Unit of Work
使用UnitOfWork特性
类public或public virtual这些基于界面的方法
像是应用服务是基于服务界面
自我注入类的public virtual方法
像是MVC Controller和Web API Controller
所有protected virtual方法
建议将方法标示为virtual
无法应用在private方法上
选项
Configuration.UnitOfWork
模块中的PreInitialize方法设置
方法
IUnitOfWorkManager.Current.SaveChanges()
在工作单元的过程中就储存所有变化
如保存变化获取新增对象的Id
发生异常回滚时,保存操作也会被回滚
事件
Completed
_unitOfWorkManager.Current.Completed += (sender, args) => { /* TODO: Send email to assigned person */ };
Failed
Disposed
数据过滤器
仅实现在EntityFramework
预定义过滤器
软删除过滤器(Soft-delete filter )
IMustHaveTenant过滤器
ABP使用IAbpSession来取得当前TenantId自动处理
管理级使用者自动禁用
IMayHaveTenant过滤器
TenantId为null时只受管理级用户掌控
禁用/启用过滤器
using IUnitOfWorkManager.Current.DisableFilter
using IUnitOfWorkManager.Current.EnableFilter
设定过滤器
CurrentUnitOfWork.SetFilterParameter("PersonFilter", "personId", 42);
CurrentUnitOfWork.SetfilterParameter(AbpDataFilters.MayHaveTenant, AbpDataFilters.Parameters.TenantId, 42);
自定义过滤器
EntityFramework.DynamicFilters
定义接口
实体声明外键
[ForeignKey("PersonId")]
重写OnModelCreating
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder.Filter("PersonFilter", (IHasPerson entity, int personId) => entity.PersonId == personId, 0 );
}
注册过滤器
Configuration.UnitOfWork.RegisterFilter("PersonFilter", false);
其它对象关系映射工具
领域事件
事件总线
默认实例
EventBus.Default
IEventBus
NullEventBus.Instance
IEventData
EventData
EventSource(那个对象触发了这个事件)
EventTime(何时触发)
定义事件
Abp.Events.Bus.Exceptions
AbpHandledExceptionData
Abp.Events.Bus.Entities
EntityCreatedEventData
EntityUpdatedEventData
EntityDeletedEventData
触发事件
EventBus.Trigger
EventBus.Trigger<TaskcompletedEventData>(new TaskCompletedEventData { TaskId = 42});
EventBus.Trigger(this, new TaskCompletedEventData { TaskId = 42 });
EventBus.Trigger(typeof(TaskCompletedEventData), this, new TaskCompletedEventData { TaskId = 42});
事件处理
基础事件处理
EventBus支持事件的继承
IEventHandler<in TEventData>
in:逆变泛型
实现HandleEvent(TEventData)
多事件处理
单个处理器继承多个事件接口,可以同时处理多个事件
注册处理器
自动注册 IEventHandler
手动注册 EventBus.Register
IEventHandlerFactory
GetHandler
ReleaseHandler
IocHandlerFactory
自动化注册
取消注册事件
EventBus.Unregister
EventBus.UnregisterAll
应用层
应用服务
IApplicationService
DTO 输入输出
IRepository 操作数据
ApplicationService基类
日志管理
本地化
LocalizationSourceName = "SimpleTaskSystem";
//获取本地化文本(L是LocalizationHelper.GetString(...)的简便版本, 定义在 ApplicationService类型)
var text = L("SampleLocalizableTextKey");
工作单元
Unit of Work(参考仓储)
生命周期
都是暂时的 Transient
数据传输对象
展现层不会直接使用领域对象(仓库,实体)
DTOs
作用
抽象领域层
隔离分层,甚至可以完全替换展现层
数据隐藏
只传递展现层需要的数据
序列号 & 惰性加载
实体对象层层引用,DTO可以更安全地序列化
按需加载数据
约定 & 验证
为每个应用服务方法创建输入输出DTO
MethodNameInput/MethodNameOutput
无参数或空返回值也创建
参数或返回值变化时不需要修改方法定义
有效性验证
IInputDto
IOutputDt
EntityDto
IDto
实体映射
AutoMapper
Mapper.CreateMap
Mapper.Map
Mapper.Map
特性+扩展方法
[AutoMap(typeof(MyClass2))] //定义映射
AutoMapExtensions.MapTo
辅助接口和类型
分页Input IPagedResultRequest
ILimitedResultRequest
MaxResultCount
SkipCount
分页Output IHasTotalCount
TotalCount
其他 Abp.Application.Services.Dto
参数有效性检验
输入数据
客户端检验
用户体验
服务端检验
DTO
IInputDto
IValidate
使用数据注解
System.ComponentModel.DataAnnotations 特性
Required
MaxLength
RegularExpression
...
自定义检验
ICustomValidate
AddValidationErrors()
results
ValidationResult
设置缺省值
IShouldNormalize
Normalize()
权限验证
定义权限
AuthorizationProvider基类
SetPermissions()
IPermissionDefinitionContext
Name(唯一)
Display Name
Description
IsGrantedByDefault
MultiTenancySides
Host
Tenant
Children(子集)
这不会影响权限检查,它只是在UI层对权限归类有好处
注册
Moudle.PreIntialize
Configuration.Authorization.Providers.Add<MyAuthorizationProvider>()
检查权限
AbpAuthorize特性
[AbpAuthorize("Administration.UserManagement.CreateUser")]
没有获得“Administration.UserManagement.CreateUser”权限的用户不能够调用特性修饰的方法
会检查是否已登录
说明
不能用于private方法
不能用于static方法
不能用于非注入类(必须用依赖注入)
app、mvc、api各自继承不同父类
疑惑:
AbpAuthorize特性可以应用于任何的Public方法,如果此方法被接口调用(比如在Application Services中通过接口调用)
方法是虚(virtual)方法,如果此方法直接被类引用进行调用(像是ASP.NET MVC 或 Web API 的控制器)。
方式是虚(virtual)方法,如果此方法是protected。
AbpAuthorize特性可以应用于任何的Public方法,如果此方法被接口调用(比如在Application Services中通过接口调用)
方法是虚(virtual)方法,如果此方法直接被类引用进行调用(像是ASP.NET MVC 或 Web API 的控制器)。
方式是虚(virtual)方法,如果此方法是protected。
AbpMvcAuthoriz
AbpApiAuthorize
IPermissionChecker
NullPermissionChecker
IsGranted
返回 ture false
Authorize
直接抛出异常
ApplicationService具有
PermissionChecker属性
PermissionChecker属性
审计日志
IAuditingStore
AuditInfo
TenantId
UserId
ServiceName
调用方法对应的类
MethodName
Parameters
JSON格式
ExecutionTime
ExecutionDuration
通常是毫秒
ClientIpAddress
ClientName
Exception
如果方法抛出异常
BrowserInfo
ImpersonatorTenantId
ImpersonatorUserId
SimpleLogAuditingStore类(module-zero)
配置
Module.PreInitialize初始化
Configuration.Auditing
IsEnabled
默认true
IsEnabledForAnonymousUsers
默认false,设置为true时未登录也记录日志
MvcControllers
在ASP.NET MVC 控制器中使用审计日志
IsEnabled
默认true,在ASP.NET MVC中启用(true)或禁用(false)审计日志
IsEnabledForChildActions
默认false,为MVC actions启用(true)或禁用(false)审计日志
Selectors
断言列表,选择使用其他类来处理审计日志的存储
特性
[Audited]
[DisableAuditing]
可加与类和方法
说明
方法必须是public
private和protected方法将被忽略
如果调用的方法不在类的引用范围内,那么引用的方法必须是虚方法(virtual),如果依赖注入的是它自己的接口则不需要是虚方法
展现层
动态生成 Web Api Controller
ForMethod("MethodName").DontCreateAction()
DynamicApiControllerBuilder.For<TAppServiceInterface>("namespace/subnamespace").Build();
api/services/’是所有动态web api的前缀,所以api地址是‘/api/services/tasksystem/task’
删除一个api方法
DynamicApiControllerBuilder.ForAll<IApplicationService>
生成所有应用服务api
服务命名约定:服务名+AppService
生成api名称为服务名,驼峰
WithServiceName 自定义名称
where过滤
动态JavaScript代理
通过ajax来动态创建web api控制器
ajax代理
ajax参数
所有代理
'/api/abpServiceProxies/GetAll'
单一服务脚本
'/api/abpServiceProxies/Get?name=serviceName
Angular框架支持
Durandal框架支持
define(['service!tasksystem/task']
通过js来动态调用web api控制器
JavaScript函数库
Ajax
与服务器通信
dataType = 'json'
type = 'POST'
contentType = 'application/json'
请求的控制器方法添加特性 [HttpPost]
请求的控制器方法返回值类型JsonResult,使用Json()函数转换
Ajax返回值
实际返回值类型MvcAjaxResponse
{
"success": true, //正确处理标志
"result": {
"personId": 42 //返回的数据
},
"error": null, //如果发生错误,result为null,此处为错误信息的对象,包含message和details两个属性
"targetUrl": null, //可以提供一个url供客户端重定向,例如自动构建下一页的url
"unAuthorizedRequest": false //是否通过了授权,如果返回true,客户端应重新登录
}
"success": true, //正确处理标志
"result": {
"personId": 42 //返回的数据
},
"error": null, //如果发生错误,result为null,此处为错误信息的对象,包含message和details两个属性
"targetUrl": null, //可以提供一个url供客户端重定向,例如自动构建下一页的url
"unAuthorizedRequest": false //是否通过了授权,如果返回true,客户端应重新登录
}
错误处理
{ "targetUrl": null, "result": null, "success": false, //代表出现异常 "error": { "message": "An internal error occured during your request!", //未捕捉到的异常,通常为系统异常,会自动记录日志,具体提示信息在配置文件配置,可以搜索一下,如果是业务抛出的UserFriendlyException异常,message为具体的错误信息 "details": "..." //发生异常时默认会调用abp.message.error函数,你可以在abp.jquery.js修改,统一处理错误信息。 }, "unAuthorizedRequest": false }
动态Web Api
通知
abp.notify
显示在右下角,自动消失
采用toastr库,可选,可替换
消息
abp.message
显示对话框
采用sweetalert库
abp.message.confirm('confirmTip','confirmTip'(可选),function (isConfirmed){})
默认js库可能会调用消息库
繁忙
半透明遮罩 UI Block Api
abp.ui.block
无参数覆盖整个页面
把jQuery对象做参数覆盖指定元素
使用选择器参数覆盖指定元素
abp.ui.unblock
指示页面繁忙
abp.ui.setBusy
参数1:同block
参数2:promise,执行完后自动解除繁忙
abp.ajax({ ... })返回promise
abp.ui.clearBusy
日志
abp.log
包装console.log,支持所有浏览器
可设置level
公共
创建命名空间别名
abp.utils.createNamespace
abp.utils = abp.utils || {};
abp.utils.strings = abp.utils.strings || {};
abp.utils.strings = abp.utils.strings || {};
第一个参数是必须存在的根命名空间
格式化字符串
abp.utils.formatString
类同string.Format
导航栏设置
创建菜单
NavigationProvider基类
INavigationProviderContext
现有菜单
添加菜单
Configuration.Navigation.Providers.Add<TNavigationProvider>();
显示菜单
服务端
IUserNavigationManager
客户端
abp.nav
abp.nav.menus.MainMenu
异常处理
异常通常在Controller actions中处理
开启异常处理
customErrors mode
On
开启
RemoteOnly
不想在本地处理这些错误
非Ajax请求
Exception
Error.cshtml
UserFriendlyException
直接显示给用户
ErrorViewModel
AbpErrorInfo
显示给用户
Exception
具体异常
Ajax请求
JSON异常信息
{ "targetUrl": null, "result": null, "success": false, "error": { "message": "An internal error occured during your request!", "details": "..." }, "unAuthorizedRequest": false }
异常事件
AbpHandledExceptionData
任何Web请求异常都会触发事件,需要注册和编写处理代码
基础设施层
EntityFramework
AbpZeroDbContext
Extensions
身份与权限
Asp.Net Identity
AbpUser
AbpUserStore
AbpUserManager
AbpRole
AbpRoleStore
AbpRoleManager
UserRole
PermissionSetting
OrganizationUnit
UserOrganizationUnit
UserLogin
PermissionChecker
...
总体介绍
技术
服务器端
ASP.NET MVC 5、Web API 2、C# 5.0
DDD领域驱动设计
Entities
Repositories
Domain Services
Domain Events
Application Services
DTOs
Castle windsor 依赖注入容器
Entity Framework 6 \ NHibernate,数据迁移
Log4Net 日志管理
AutoMapper DTO与实体类双向自动转换
Asp.Net Identity
Newtonsoft.Json
客户端
Bootstrap
AngularJs
angularjs-ui
angular-ui-jq (在ui-utils.js中)
angular-bootstrap-switch
angular-daterangepicker
angular-moment
angular-file-upload
AngularJS API (1.6.2版本)
jQuery
Modernizr 浏览器兼容
JsTree
UI-Select bootstrap-select
UI-Grid
UI-Layout
其他
jQuery.validate、jQuery.form、jQuery.blockUI、json2
实现功能特性
Model-Zero
身份验证与授权管理
Asp.Net Identity
用户&角色管理
系统设置存取管理
系统级、租户级、用户级,作用范围自动管理
审计日志
自动记录每一次接口的调用者和参数
分层结构
展现层 Presentation
View Models(Javascript)
Views(HTML/CSS)
Localization
控制器 Web
Web Api Controllers
Mvc Controllers
应用层 Application
Application Services
DTOs
DTO Mappers
领域层 Domain
Entities
Value Objects
Respositories
Business Classes
Domain Services
Unit of Work
Domain Events
基础设施层 Infrastructure
ORM
EntityFramework
NHibernate
...
DB Migrations
其他 Others
依赖注入 Dependency Injection
Castle Windsor
日志管理 Logging
Log4Net
模块系统
AbpModule
PreInitialize
配置 Configuration
Initialize
依赖注入注册
PostInitialize
提交初始化,解析依赖关系
Shutdown
应用关闭后调用
模块依赖
[DependsOn(typeof(MyBlogCoreModule))]//通过注解来定义依赖关系
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());//这里,进行依赖注入的注册。
启动配置
配置是通过在自己模块的PreInitialize方法中来实现的
通过IAbpModuleConfigurations进行个性化的扩展
依赖注入
传统方式的问题
组件实现接口,依赖性倒置
PersonAppService通过IPersonRepository调用CreatePerson方法,所以这方法依赖于IPersonRepository,代替了PersonRepository具体类。但PersonAppService(的构造函数)仍然依赖于PersonRepository。组件应该依赖于接口而不是实现。这就是所谓的依赖性倒置原则。
工厂模式仍有一个硬依赖,
为每个库或每个依赖项乏味的写一个工厂类/方法
ABP依赖注入
常规注册
Repositories
Domain Services
Application Services
MVC Controllers
Web Api Controllers
帮助接口
ITransientDependency
ISingletonDependency
自定义/直接 注册
Castle Windsor
Component.For<IPersonRepository>().ImplementedBy<PersonRepository>().LifestyleTransient()
解析
构造函数 & 属性注入
使用DI系统最适当的方式
IIocResolver 和 IIocManager
直接创建依赖项
附加
IShouldInitialize
Initialize()
集成 ASP.NET MVC & ASP.NET Web API
依赖注入控制器
不用关心对象的创建和释放,由框架完成
Session管理
IAbpSession
AbpSession属性(module-zero)
ApplicationService
AbpController
AbpApiController
UserId
TenantId
MultiTenancySide(Host|Tenant)
区别于System.Web.HttpSessionStateBase
即使Web服务重启,也不会丢失Session状态
日志管理
服务器
ILogger
Log4Net
Logger属性
MVC Controllers
Web API Controllers
Application service classes
NullLogger.Instance
默认配置
Log level
DEBUG
INFO
WARN
ERROR
FATAL
Date and time
Thread number
Logger name
Log text
Log4net.config
file
appendToFile
rollingStyle
maxSizeRollBackups
maximumFileSize
staticLogFileName
layout type
conversionPattern value
logger level
客户端
javascript api
console.log
abp.log
abp.log.debug('...')
abp.log.info('...')
abp.log.warn('...')
abp.log.error('...')
abp.log.fatal('...')
设置管理
ISettingStore
SettingProvider
SettingDefinition
Name
Default value
Scopes
Display name
Description
Group
IsVisibleToClients
SettingScopes
Application
Tenant
Flags
Application | Tenant | User
先后尝试获取设置User>>Tenant>>Application
User
获取设置值
服务器
ISettingManage
SettingManager属性
ApplicationService
DomainService
AbpController
GetSettingValue
客户端
javascript
abp.setting
get
getInt
getBoolean
...
更改设置
ISettingManager
ChangeSettingForApplication
ChangeSettingForTenant
ChangeSettingForUser
缓存设置
缓存在服务器端设置管理,所以,我们不应直接使用存储库或数据库更新语句改变设置的值
收藏
0 条评论
下一页