Spiga

ABP成长系列7:数据访问

2024-06-01 16:01:56

摘要:一、仓储 仓储模式是ABP框架数据访问层的核心抽象,它提供了一种统一的方式来访问数据源,无论底层使用何种数据库技术(EF Core、MongoDB等)。 接口抽象:框架定义了一系列通用的仓储接口,如 IRepositoryTEntity, TKey。你的领域层和应用层只依赖于这些接口,而不是具体的实现,这严格遵循了DDD的持久化无关原则。 默认实现:ABP为EF、MongoDB和Dapper提供了这些仓储接口的开箱即用的实现。这意味着对于大多数标准的CRUD操作,无需编写任何仓储实现代码。 自定义仓储:对于复杂的查询或特定操作,可以定义自定义的仓储接口(如 ICustomRepository),并在基础设施层(如EntityFrameworkCore项目)中实现它。ABP的依赖注入系统会自动将其注册到容器中。 类关系图 1. 仓储接口体系 ABP定义了一套完整的仓储接口体系,位于Volo.Abp.Domain.Repositories命名空间: //IRepository.cs public interface IRepository { } public interface IRepositoryTEntity : IReadOnlyRepositoryTEntity, IBasicRepositoryTEntity where TEntity : class, IEntity { TaskTEntity FindAsync([NotNull] ExpressionFuncTEntity, bool predicate, bool includeDetails = true, CancellationToken cancellationToken = default); TaskTEntity GetAsync([NotNull] ExpressionFuncTEntity, bool predicate, bool includeDetails = true, CancellationToken cancellationToken = default); Task DeleteAsync([NotNull] ExpressionFuncTEntity, bool predicate, bool autoSave =…… 阅读全文

ABP成长系列6:DDD

2024-05-25 11:56:40

摘要:ABP是一个面向DDD的项目框架,接下来的内容将学习如何利用ABP来落地DDD的项目,我们今天先来总结一下DDD的核心思想。 一、什么是领域驱动设计 1. 传统软件开发 业务梳理 == 软件设计 == 开发 初期-简单-迭代-复杂-冗杂-屎山代码-牵一发而动全身-重构系统-演进 示例:订单服务(查询订单、创建订单、订单评价、支付……) 项目流程:讨论需求==数据库建模==项目开发==迭代数据库的设计==上线 2. 领域驱动开发 根据领域知识一步步驱动软件设计的过程就是领域驱动设计(DDD,Domain-Driven Design) 领域驱动设计(DDD)是一种处理高度复杂领域的设计思想 设计思想:通过分离技术实现的复杂性,并围绕业务概念构建领域模型来控制业务的复杂性 项目流程:领域模型=数据库设计 3. 战略设计和战术设计 领域驱动设计包括战略设计和战术设计两部分: 战略设计:从业务视角出发=》业务领域模型=》边界=》通用语言的限界上下文 战术设计:从技术视角出发=》技术实现=》实体、聚合根、值对象、领域服务…… 二、领域驱动设计的基础概念 1. 领域和子域 领域(业务问题域)具体指一种特定的范围或区域,就是用来确定范围的,范围就是边界 细分-限定-领域模型-代码实现 领域越大业务范围就越大 领域可以进一步划分为子领域(子域 更小的) 子域对应一个更小的范围 我们来看一张经典的图 给桃树建立领域知识的步骤: 确定研究对象 对研究对象进行细分 对子对象再次进行细分 细分到最小单元 再来看一个电商项目的领域划分的例子: 电商领域可以分成:商品子域、销售子域、订单子域、物流子域 物流子域又可以分成:拣货子域、发货子域、派送子域 领域建模的过程和方法其核心思想就是将问题域逐步分解 降低业务理解和系统实现的复杂度 2. 核心域、通用域和支撑域 核心域:产品核心业务功能 通用域:被多个子域使用的通用功能(认证、授权、日志) 支撑域:既不包含业务核心功能,也不包含通用功能 电商平台中:销售子域是核心域,物流子域是支撑销售业务的,所以它的支撑域 植物研究领域中,需要根据不同情况来划分核心域 如果是在果园:果实就是核心域。为了让果实更饱满,果农可能会裁剪一些枝和叶 如果是在公园:花就是核心域 3. 通用语言 通过团队交流达成共识的,能够简…… 阅读全文

ABP成长系列4:认证授权

2024-05-11 11:49:34

摘要:ABP框架并不重新发明轮子去实现认证,而是完美集成并简化了上述ASP.NET Core的认证流程。 模块化封装:当你使用ABP的启动模板时,认证的配置通常已经在模块中预先配置好,你只需要在appsettings.json中提供必要的参数(如JWT的签发者、密钥等)。 依赖注入集成:ABP通过ICurrentUser提供了对当前登录用户ID (UserId) 和租户ID (TenantId) 的便捷访问。这个接口的背后实现正是基于HttpContext.User及其声明(Claims)。 多租户支持:ABP的认证系统天然支持多租户,可以正确处理不同租户下的用户登录和会话管理。 ABP的主要价值在于整合与简化,它让你在使用强大的ASP.NET Core认证机制的同时,享受到ABP模块化和约定优先开发模式带来的便捷。 要学习好ABP的认证授权模块,我们来看一下ASP.NET Core的认证授权。 一、ASP.NET Core认证授权 1. 基本流程 UseAuthentication + AddAuthentication UseAuthorization + AddAuthorization(.net源码内置) [Authorize] [AllowAnonymous] 未登陆—访问—登陆—访问—退出 2. 理解认证 认证就是鉴别是张三----解读请求携带的用户信息 信息位置:怎么传递的凭证?Cookie,JWT,Other 信息格式:凭证是什么格式,加密问题 信息有效性:token过期了、签名不对 认证后信息保存:保存到context.User里面 特殊情况处理:没登陆、没权限、没xxx,这些就是认证需要知道的,需要干的活儿 登陆是怎么配合的?HttpContext.SignInAsync完成用户信息的写入(如:Cookie) 3. 理解授权 授权:就是检测下用户到底有没有权限访问某个方法 认证和授权的关系? 没有直接关系,认证获取用户信息保存到context.User,授权去使用 授权的时候,会用Scheme去认证一下,还有异常处理 检测凭据: 标记特性[Authorize] [AllowAnonymous]—就做授权检测 ASP.NET Core提供了灵活且强大的授权策略模型,主要包括: 基于角色的授权 ([Authorize(Roles =…… 阅读全文

ABP成长系列3:DI

2024-05-04 11:03:40

摘要:前面重点介绍了ABP.vNext的模块化,以及模块化带来的核心价值动态API,今天我们开看一下ABP DI的扩展。 一、ABP DI功能介绍 1. 组件自动注册 SkipAutoServiceRegistration AddAssemblyOf AddAssembly public class BlogModule : AbpModule { public override void PreConfigureServices(ServiceConfigurationContext context) { SkipAutoServiceRegistration = true; } public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAssemblyOfBlogModule(); } } 2. 默认的注册 模块类注册为singleton MVC控制器(继承Controller或AbpController)被注册为transient MVC页面模型(继承PageModel或AbpPageModel)被注册为transient MVC视图组件(继承ViewComponent或AbpViewComponent)被注册为transient 应用程序服务(实现IApplicationService接口或继承ApplicationService类)注册为transient 存储库(实现IRepository接口)注册为transient 域服务(实现IDomainService接口)注册为transient 3. 依赖接口 ITransientDependency 注册为transient生命周期 ISingletonDependency 注册为singleton生命周期 IScopedDependency 注册为scoped生命周期 4. 特性 DependencyAttribute:控制服务的注册行为和生命周期 ExposeServicesAttribute:控制服务以哪些类型注册到容器中 [ExposeServices(typeof(…… 阅读全文

ABP成长系列2:动态API

2024-04-27 10:54:32

摘要:前面我们介绍了Abp的模块化,号称能随意拆分,随意组装, 能各种复用,是真的超牛。 但是这样就可以了吗?虽然是可以任意组装了,比如A项目被拆分成A、B两个项目了。如何才能做的优雅,做的有意义? ABP的答案是这样的: 最强CP——ADO(Auto API+Dynamic Client+Options) 模块化===能力复用 Auto API Controller:轻松组合到一个进程,也可以模块化独立部署,拆分分布式 Dynamic C# Client:服务之间的调用(跟本地调用一样),都不用改代码,就可以轻松替换成分布式调用 定制化需求:Options选项模式完成定制 一、Auto API Controllers 创建应用程序服务后, 通常需要创建API控制器以将此服务公开为 HTTP(REST)API端点 典型的API控制器除了将方法调用重定向到应用程序服务并使用[HttpGet],[HttpPost],[Route]等属性配置REST API之外什么都不做 瘦控制器:本身是可以不要的 ABP可以按照惯例自动将应用程序服务配置为API控制器 大多数时候不关心它的详细配置,但它可以完全被自定义,而且还可以做好复用 Auto-API-Controllers自动API控制器,可以不用写控制器Action了,就可以直接把应用服务暴露成WebAPI 1. 配置方法 服务标记成IRemoteService 配置AbpAspNetCoreMvcOptions TypePredicate ConventionalControllers.Create 以上就完成了Auto-API-Controller 2. 自定义HttpMethod ABP在确定服务方法的HTTP Method时使用命名约定: Get:如果方法名称以GetList,GetAll或Get开头 Put:如果方法名称以Put或Update开头 Delete:如果方法名称以Delete或Remove开头 Post:如果方法名称以Create,Add,Insert或Post开头 Patch:如果方法名称以Patch开头 其他情况,Post 为 默认方式 自定义HTTP Method,则可以使用标准ASP.NET Core的属性 ([HttpPost], [HttpGet], [HttpPut]..…… 阅读全文

ABP成长系列1:模块化

2024-04-20 12:36:10

摘要:在讲ABP的模块实现前,我们先来认识一下ABP。 一、初识ABP 1. ABP vNext是什么 ASP.NET Core的开源WEB应用程序框架——就是再封装一层,扩展了一系列的封装,完成了很多通用的。 ABP是用于创建现代Web应用程序的完整架构和强大的基础设施! 遵循最佳实践和约定,为你提供SOLID开发经验 https://www.abp.io/ https://github.com/abpframework/abp 2. 架构特点 应用程序模块化 领域驱动设计DDD 微服务架构 支持仓储,基于O/RM实现数据库无关性和MongoDB集成 可扩展及可替换 3. 基础设施 领域驱动设计 模块化设计 多租户 Dependency Injection 认证与授权 事件总线 数据访问 Auto API及动态代理 4. 其他组件 横切面关注 虚拟文件系统 数据过滤 本地化 异常处理 审计日志 二、开启ABP.vNext 1. 使用 ABP CLI 工具直接生成 超多内容,请自行查看。https://docs.abp.io/zh-Hans/abp/latest/CLI 也可以在 https://abp.io 直接生成 可以查看基础项目 BookStore,账号 admin,密码 1q2w3E* 自动化生成一次性生成了太多代码,不适合学习,接下来我们要研究一下手动集成 2. 手动集成控制台项目 手动创建一个.net core控制台项目,添加核心nuget包,Volo.Abp 创建一个HelloWorldService服务,使用瞬时生命周期 [Dependency(ServiceLifetime.Transient)] public class HelloWorldService() { public void Run() { Console.WriteLine(Hello World); } } ABP是模块化的,所以我们要创建一个模块类 AppModule public class AppModule : AbpModule { public override void OnApplicationInitialization(ApplicationInitializationContext …… 阅读全文

ASP.NET Core 7 源码阅读8:阅读脑图

2023-10-03 15:34:17

摘要: 阅读全文

ASP.NET Core 7 源码阅读7:CAR

2023-09-25 23:01:42

摘要:一、CAR 1. CAR本质 URL请求----调用Action----生成html响应(或其他响应) CAR就是个普通类---普通方法---最终生成HTML(也可能是其他的) 一个URL,怎么调用的Action---一定是反射----反射创建控制器实例,反射准备方法参数,反射调用Action方法(也许来点优化) 然后生成一段内容(啥都可以),写入到Response里面---然后由Kestrel回发到浏览器----浏览器解析报文做呈现 先Get这个本质,不要被各种封装各种特性看花眼了~ 2. 关键节点-上帝视角 CAR虽然是最后才生效,但是在前面也出现了---全流程debug一下,回顾一下: 启动环节services.AddControllers注册IOC时扫描dll,保存到ApplicationManager 初始化中间件MapControllerRoute()转成ControllerActionDescripter 第一次请求进入,路由初始化DFAMatcher时触发转换成Endpoint,路由匹配找到Endpoint---鉴权授权--- 执行Endpoint时实例化和缓存各种工厂、 Filter等---做好调用准备 执行Filter管道, ActionBegin状态实例化控制器, Bind参数 ActionInside状态开始执行Action,得到ActionResult ResultInside状态开始执行ExecuteResult,得到结果 Controller-Action-Result流程结束 3. CAR源码 按照主流程往后走,先关注Controller,再Action,再Result,其中会有回溯 步骤1: services.AddControllers注册时扫描dll,转成ApplciationPart,保存到ApplciationPartManager 知识点:当前项目引用的dll都算数,所以是独立类库---扩展PartDemo 收集完的内容都是保存在ApplciationPartManager—等于是个中间层,其实就可以开个后门,通过其他方式添加数据进去---所以可以热插拔 甚至可以动态编译脚本---后插拔进去 步骤2:初始化中间件MapControllerRoute()注册UpdateCollection,注册Updat…… 阅读全文

ASP.NET Core 7 源码阅读6:Filter

2023-08-20 21:32:52

摘要:一、快速认识Filter 1. 流程衔接点 MVC(Filter+Controller+Action+Result)流程和前面的各种中间件Middleware处理,是如何衔接起来的? Http请求穿过一系列中间件,最终由路由RoutingMiddleware匹配得到RouteEndpoint 在EndpointMiddleware里面会执行其RequestDelegate,委托执行时就是FilterController-Action-Result 该委托在ControllerRequestDelegateFactory里面来构建的,里面通过ControllerActionInvoker来调用 这里有个新名字叫 FilterPipeline 2. 快速认识Filter Filter是MVC里面核心组成部分,有着丰富的种类,交叉的顺序,复杂的嵌套,很有挑战! Filter分2种: 声明特性,实现Filter接口:CustomSimpleShowActionFilterAttributeCustomSimpleShowAsyncActionFilterAttributeCustomSimpleShowDoubleActionFilterAttribute:一个Filter里面既有同步,又有异步,只执行异步!能改参数,能改结果,非常强大注意异步版本的结果修改坑 控制器类实现Filter接口包括Action同步异步-Result同步异步---控制器生效,全部Action都有效 3. AOP面向切面编程 要说Filter,得理解下AOP面向切面编程Aspect Oriented Programming POP面向过程,没有封装没有边界,难以应对复杂需求OOP面向对象,有封装有边界,能应付复杂需求,但原子---类---不容破坏,否则会影响稳定性---开闭原则 AOP能在不破坏封装的前提下,去额外扩展功能比如ActionFilter,啥都没修改,就能增加执行逻辑AOP的好处: 聚焦业务逻辑,轻松扩展功能 代码复用,集中管理 4. 框架中的AOP 现代化开发框架中,要灵活应用AOP面向切面编程思想: ASP.NET Core三层AOP 中间件:离MVC比较远,面向与请求级的事儿 Filter:更贴近MVC,面向单个请求,更细一些 IOC容器的AOP扩展:细化到具体业…… 阅读全文

ASP.NET Core 7 源码阅读5:认证授权

2023-07-10 16:20:24

摘要:从Http无状态协议---用户持久化的需求---最初是Cookie+Session---Token但是不管是哪种方式,有一段内容是不变的: 请求服务端,获取凭证 客户端再次请求,带上凭证 服务端识别凭证,判断是否允许访问 认证授权的本质是做啥的? 其实就是第3步解决用户识别和判断授权的问题被拆分成了2个动作: 认证Authentication:凭证识别解析,有没有登陆,凭证有没有过期,是张三还是李四 授权Authorization:基于解析来权限检测,判断下张三/李四有没有权限访问这个资源 一、实操 1. 没有任何权限要求实操 添加相关控制器, Cookie式登陆方法 UseAuthentication + AddAuthentication + Cookie UseAuthorization + AddAuthorization(可不写) [Authorize] [AllowAnonymous] 校验流程: 未登陆,直接访问,跳转登录页 AllowAnonymous可直接访问 登陆后跳转,正常访问 退出后访问,跳转登陆页 2. 授权 Roles授权: [Authorize(Roles = Admin)] Policy授权: [Authorize(Policy = AdminPolicy)] 复杂Policy授权: [Authorize(Policy = MutiPolicy)] 授权的设计,也是可以满足开发者各种这样的需求—目前还没演示完 如果是没有登陆,是跳转LoginPath---401 如果是有凭证,但没有权限,是跳转AccessDeniedPath--403 3. 发送了什么? 请求到达Action之前,即使没有标记,也会自动认证 主动认证:理解认证信息保存 主动授权:理解授权检测过程 4. 理解总结 认证授权是ASP.NET Core框架封装的2个中间件,目的在于请求进入具体的Filter-M-V-C之前,通过中间件完成用户权限检测包含2个步骤: 认证Authentication:鉴别有没有登陆,解析是张三还是李四(且将信息传递下去)---UseAuthentication配置Http管道,保证请求来了,都要做一次凭证的解析AddAuthentication配置IOC,告诉如何认证(凭证在那儿,啥格式的) 授权Authori…… 阅读全文