百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

ABP开发框架的技术点分析(1)(abp开源框架)

ccwgpt 2024-09-20 13:34 27 浏览 0 评论

ABP是ASP.NET Boilerplate的简称,ABP是一个开源且文档友好的应用程序框架。ABP不仅仅是一个框架,它还提供了一个最有实践的基于领域驱动设计(DDD)的体系结构模型。ABP框架可以说是.net core整合非常多技术点的一个很好的框架,整个涉及到很多非常多方面的知识。我们来大概了解下ABP框架涉及到的内容。

  • 依赖注入,这个部分使用 Castle windsor (依赖注入容器)来实现依赖注入,这个也是我们经常使用IOC来处理的方式;
  • Repository仓储模式,已实现了Entity Framework、NHibernate、MangoDB、内存数据库等,仓储模式可以快速实现对数据接口的调用;
  • 身份验证与授权管理,可以使用声明特性的方式对用户是否登录,或者接口的权限进行验证,可以通过一个很细粒度的方式,对各个接口的调用权限进行设置;
  • 数据有效性验证,ABP自动对接口的输入参数对象进行非空判断,并且可以根据属性的申请信息对属性的有效性进行校验;
  • 审计日志记录,也就是记录我们对每个接口的调用记录,以及对记录的创建、修改、删除人员进行记录等处理;
  • Unit Of Work工作单元模式,为应用层和仓储层的方法自动实现数据库事务,默认所有应用服务层的接口,都是以工作单元方式运行,即使它们调用了不同的存储对象处理,都是处于一个事务的逻辑里面;
  • 异常处理,ABP框架提供了一整套比较完善的流程处理操作,可以很方便的对异常进行进行记录和传递;
  • 日志记录,我们可以利用Log4Net进行常规的日志记录,方便我们跟踪程序处理信息和错误信息;
  • 多语言/本地化支持,ABP框架对多语言的处理也是比较友好的,提供了对XML、JSON语言信息的配置处理;
  • Auto Mapping自动映射,这个是ABP的很重要的对象隔离概念,通过使用AutoMaper来实现域对象和DTO对象的属性映射,可以隔离两者的逻辑关系,但是又能轻松实现属性信息的赋值;
  • 动态Web API层,利用这个动态处理,可以把Application Service 直接发布为Web API层,而不需要再累赘的为每个业务对象手工创建一个Web API的控制器,非常方便;
  • 动态JavaScript的AJax代理处理,可以自动创建Javascript 的代理层来更方便使用Web Api,这个在Web层使用。

1、ABP应用框架项目结构

一般我们涉及到的ABP框架,可能解决方案上都会有这些项目。

而这些项目使用了ABP框架的底层框架模块,使用基础模块可以极大简化应用框架的规模,提高效率,并抽象常规的功能和约定处理,如下所示。

基础的ABP框架实现(地址https://github.com/aspnetboilerplate/aspnetboilerplate),这个是我们所说的ABP框架的核心实现;

上面提到的在基础ABP框架基础上实现处理的ABP应用框架,如下所示。

它主要是分为下面几个项目分层。

Core领域核心层,领域层就是业务层,是一个项目的核心,所有业务规则都应该在领域层实现。这个项目里面,除了定义所需的领域实体类外,其实可以定义我们自己的自定义的仓储对象(类似DAL/IDAL),以及定义自己的业务逻辑层(类似BLL/IBLL),以及基于AutoMapper映射规则等内容。

EntityFrameworkCore 实体框架核心层,这个项目不需要修改太多内容,只需要在DbContext里面加入对应领域对象的仓储对象即可。

Application.Common和Application应用层:应用层提供一些应用服务(Application Services)方法供展现层调用。一个应用服务方法接收一个DTO(数据传输对象)作为输入参数,使用这个输入参数执行特定的领域层操作,并根据需要可返回另一个DTO。

Web.Core Web核心层,基于Web或者Web API的核心层,提供了对身份登陆验证的基础处理,没有其他内容。

Web.Core.Host Web API的宿主层,也是动态发布Web API的核心内容,另外在Web API里面整合了Swagger,使得我们可以方便对Web API的接口进行调试。

Migrator数据迁移层,这个是一个辅助创建的控制台程序项目,如果基于DB First,我们可以利用它来创建我们项目的初始化数据库。

2、ABP框架的动态Web API

我们知道,一般我们发布需要实现Web API的发布,需要创建对应的Web API控制器内,然后在Web API应用中注册对应的路由来处理。由于ABP框架的Application Service层已经是无限接近Web API层的定义了,而且本身ABP框架已经抽象划分了几个不同的分层,再引入一个类似Application Service层的Web API层,显得多余且累赘,所以ABP框架约定了Application Service层继承接口和命名规则,也是为引入动态Web API做铺垫的,用一个通用的Host层,统一动态发布所有的Web API层,减轻了繁复且累赘的Web API 控制器的定义。

使用ABP自带的例子来说明,例如有如下的接口定义。

public interface ITaskAppService : IApplicationService
{
    GetTasksOutput GetTasks(GetTasksInput input);
    void UpdateTask(UpdateTaskInput input);
    void CreateTask(CreateTaskInput input);
}

然后其使用动态发布Web API的方式类似如下逻辑所示。

Configuration.Modules.AbpWebApi().DynamicApiControllerBuilder.For<ITaskAppService>("tasksystem/task").Build();

当然这个是对于特定的接口的处理,通用的动态Web API发布处理,会通过反射获得对应的接口列表,然后是逐一进行处理的。

我们这里如果需要详细追究ABP的动态Web API发布的规则处理,可以参考ABP的基础框架部分,了解 DynamicApiControllerBuilder 的处理逻辑即可。

而ABP框架动态发布Web API,对应的控制器的方法,约定会根据命名规则进行处理,默认一般为Post,规则如下所示:

  • Get: 如果方法名以 'Get'开始
  • Put: 如果方法名以 'Put' 或 'Update' 开始
  • Delete: 如果方法名以 'Delete' 或 'Remove' 开始
  • Post: 如果方法名以 'Post' 、 'Create' 或 'Insert' 开始.
  • Patch: 如果方法名以 'Patch' 开始.
  • 默认以 POST 方式作为 HTTP 动作.

有了动态发布Web API层,我们就不需要在Web API层中复制一份类似Application Service的定义和实现了,这样可以省却很多麻烦事情,减少维护的代码。

3、依赖注入的仓储模式

ABP使用并提供常规的依赖注入。可以简单地注入任何依赖项(例如:IRepository <Authorization.Tasks.Task>)

依赖注入其实也是IOC,实现了接口的控制反转,可以在程序启动的时候,统一根据接口加载对应的实现,而使用的时候,我们只需要知道接口的使用方法即可。现在的Entity Framework 实体框架都是基于IOC实现的了。

我们这里假设您已经知道依赖注入带来的好处和大概的处理,依赖注入一般分为构造函数的注入,和属性注入。让我们来看看一个具体的依赖注入实现的代码。

public class TaskAppService : ApplicationService, ITaskAppService
{
    private readonly IRepository<Task> _taskRepository;

    public TaskAppService(IRepository<Task> taskRepository)
    {
        _taskRepository = taskRepository;
    }

    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("CouldNotFindTheTaskMessage"));
        }

        ObjectMapper.MapTo(input, task);
    }
}

这里的_taskRepository 就是仓储接口的依赖注入,这个具体的实现是在启动的时候,有IOC容器进行动态的加入。使用的时候我们在各个函数里面都是调用对应的仓储接口(而不是实现)来处理信息的。

属性注入的做法类似只是提供了一个Public的属性定义供动态设置属性接口。

public class PersonAppService
{
    public ILogger Logger { get; set; }

    private IPersonRepository _personRepository;

    public PersonAppService(IPersonRepository personRepository)
    {
        _personRepository = personRepository;
        Logger = NullLogger.Instance;
    }

    public void CreatePerson(string name, int age)
    {
        Logger.Debug("Inserting a new person to database with name = " + name);
        var person = new Person { Name = name, Age = age };
        _personRepository.Insert(person);
        Logger.Debug("Successfully inserted!");
    }
}

ABP的依赖注入基于 Castle Windsor框架。Castle Windsor最成熟的DI框架之一。还有很多这样的框架,如Unity,Ninject,StructureMap,Autofac等等。

接口的实例初始化,一般我们启动程序的时候,使用IoC容器进行统一的处理,如下所示。

var container = new WindsorContainer();

container.Register(
        Component.For<IPersonRepository>().ImplementedBy<PersonRepository>().LifestyleTransient(),
        Component.For<IPersonAppService>().ImplementedBy<PersonAppService>().LifestyleTransient()
    );

var personService = container.Resolve<IPersonAppService>();
personService.CreatePerson("John Doe", 32);

而在ABP框架里面,一般可以通过 IocManager 来根据程序集统一进行接口的实例化处理,按照约定注册程序集。

IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());

Assembly.GetExecutingAssembly()得到一个对包括此代码的程序集的引用。按照约定,ABP自动注册所有 Repositories, Domain Services, Application Services, MVC 控制器和Web API控制器。

另外,ABP框架的数据处理采用了EF框架的仓储模式来处理数据的增删改查等处理,可以实现多种数据库的兼容,而且能够抽象实现常规数据操作接口,以及提供非常方便的LINQ处理方式。

在ABP中,仓储类要实现IRepository接口。在ABP基础模块中,它的接口定义如下所示。

对于仓储类,IRepository定义了许多泛型的方法。比如: Select,Insert,Update,Delete方法(CRUD操作)。在大多数的时候,这些方法已足已应付一般实体的需要。

一般我们定义一些对应的DTO以及领域对象,然后依据对应的接口来实现业务对象的仓储处理。

例如对于字典类型来说,定义的领域对象如下所示。

namespace MyProject.Dictionary
{
    [Table("TB_DictType")]
    public class DictType : FullAuditedEntity<string>
    {
        /// <summary>
        /// 类型名称
        /// </summary>
        [Required]
        public virtual string Name { get; set; }

        /// <summary>
        /// 字典代码
        /// </summary>
        public virtual string Code { get; set; }

        /// <summary>
        /// 父ID
        /// </summary>
        public virtual string PID { get; set; }

        /// <summary>
        /// 备注
        /// </summary>
        public virtual string Remark { get; set; }

        /// <summary>
        /// 排序
        /// </summary>
        public virtual string Seq { get; set; }
    }
}

然后在应用层就直接使用通用的仓储对象接口即可。

    /// <summary>
    /// 字典类型应用服务层实现
    /// </summary>
    [AbpAuthorize]
    public class DictTypeAppService : MyAsyncServiceBase<DictType, DictTypeDto, string, DictTypePagedDto, CreateDictTypeDto, DictTypeDto>, IDictTypeAppService
    {
        /// <summary>
        /// 标准的仓储对象
        /// </summary>
        private readonly IRepository<DictType, string> _repository;

        public DictTypeAppService(IRepository<DictType, string> repository) : base(repository)
        {
            _repository = repository;
        }

        ............

    }

因为这些通用的仓储对象接口已经很多,常规都是够用的,而不需要进行特定仓储对象的自定义封装处理,否则徒增烦恼。


原文地址:https://www.cnblogs.com/wuhuacong/p/13595291.html

相关推荐

Spring WebFlux vs. Spring MVC(springboot是什么)

背景随着异步I/O和Netty等框架的流行,响应式编程逐渐走入大众的视野。但是,响应式编程本身并不是太新的概念,这个术语最早出现在1985年DavidHarel和AmirPnue...

深度解析微服务高并发:适配SpringMVC框架适配模块及实现原理

适配主流框架如果不借助Sentinel提供的适配主流框架的模块,则在使用Sentinel时需要借助try-catchfinally将要保护的资源(方法或代码块)包起来,在目标方法或代码块执行之前,调...

Spring MVC 底层原理深度解析:从请求到响应的全链路拆解

一、Servlet容器与DispatcherServlet的启动博弈1.Tomcat初始化阶段java//Tomcat初始化流程StandardContext#startInterna...

改造总结之传统SpringMVC架构转换为SpringBoot再到集群

改造出发点,是基于现在服务都在向上云的目标前进,传统SpringMVC难以满足项目持续构建、服务节点任意扩展的需求,所以开始了历史项目的改造。项目改造考虑的主要是兼容以前的业务代码,以及session...

SpringBoot3 整合 Spring MVC 全解析:开启高效 Web 开发之旅

在当今的JavaWeb开发领域,Spring框架家族无疑占据着重要的地位。其中,SpringBoot3和SpringMVC更是开发者们构建强大、高效Web应用的得力工具。今天,...

一文读懂SpringMVC(一文读懂!残疾人低保边缘家庭能领的超实用福利政策)

1.SpringMVC定义1.1.MVC定义Model(模型):是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据View(视图):是应用程序中处理数据显示的部分。通常...

69 个Spring mvc 全部注解:真实业务使用案例说明(必须收藏)

SpringMVC框架的注解为Web开发提供了一种简洁而强大的声明式方法。从控制器的定义、请求映射、参数绑定到异常处理和响应构建,这些注解涵盖了Web应用程序开发的各个方面。它们不仅简化了编码工作,...

Spring MVC工作原理:像拼积木一样构建Web应用

SpringMVC工作原理:像拼积木一样构建Web应用在Java的Web开发领域,SpringMVC无疑是一个让人又爱又恨的存在。它像一位神通广大的积木搭建大师,将一个个分散的功能模块巧妙地拼接在...

5千字的SpringMVC总结,我觉得你会需要

思维导图文章已收录到我的Github精选,欢迎Star:https://github.com/yehongzhi/learningSummary概述SpringMVC再熟悉不过的框架了,因为现在最火的...

SpringMVC工作原理与优化指南(springmvc工作原理和工作流程)

SpringMVC工作原理与优化指南在现代Java开发中,SpringMVC无疑是构建Web应用程序的首选框架之一。它以其优雅的设计和强大的功能吸引了无数开发者。那么,SpringMVC究竟是如何工作...

Spring MVC框架源码深度剖析:从入门到精通

SpringMVC框架源码深度剖析:从入门到精通SpringMVC框架简介SpringMVC作为Spring框架的一部分,为构建Web应用程序提供了强大且灵活的支持。它遵循MVC(Model-V...

3000字搞明白SpringMVC工作流程、DispatcherServlet类、拦截器!

SpringMVC基础虽然SpringBoot近几年发展迅猛,但是SpringMVC在Web开发领域仍然占有重要的地位。本章主要讲解SpringMVC的核心:DispatcherServlet类...

多年经验大佬用2000字透彻解析SpringMVC的常用注解及相关示例

SpringMVC注解SpringMVC框架提供了大量的注解,如请求注解、参数注解、响应注解及跨域注解等。这些注解提供了解决HTTP请求的方案。本节主要讲解SpringMVC的常用注解及相关示例...

知乎热议:如何成为前端架构师,赚百万年薪?

作者|慕课网精英讲师双越最近有一条知乎热议:从一个前端工程师,如何根据目标,制定计划,才能快速进阶成为前端架构师?不久之前我参与了一次直播,讲到了自己对于Web前端架构师的理解。架构师这个角色...

学习笔记-前端开发架构设计(前端架构设计方案)

前端开发的技术选项主要包含以下几点,下面对一些名词概念的解释做了笔记:1、分层架构:把功能相似,抽象级别相近的实现进行分层隔离优势:松散耦合(易维护,易复用,易扩展)常见分层方式:MVC,MVVM2、...

取消回复欢迎 发表评论: