ABP框架 - 介紹

在14,15年間帶領幾個不一樣的團隊,交付了幾個項目,在這個過程當中,雖然幾個項目的業務不同,可是不少應用程序架構基礎性的功能倒是大同小異,例如認證、受權、請求驗證、異常處理、DTO、日誌、審計、定時任務、調度、多語言、應用配置管理等等這些功能。可是因爲項目受限於進度、資源、團隊成員的背景,在當時卻難於作到各個項目的統一,只能用拷貝的方式,而後在不通的項目中各自再根據各自的需求去作改進。這促使我下定決心去整理實現一個通用的應用程序級別的框架,來提高項目交付的效率和質量。前端

在整理這個框架的過程當中,參考了一些開源框架的設計和實現,無心中發現了ABP(ASP.NET Boilerplate)已經實現的正是我想要的,本着不重複造輪子的原則,在對ABP作了POC和評估後,在向整個評審小組展現時,儘管有諸多細節你們意見不盡相同,但對於總體框架倒是少有的一致好評,在後來的項目交付中使用ABP也就是順利成章的事了。當時ABP的版本仍是0.5(如今的最新版本是3.5),儘管也踩了一些坑,可是總的來講仍是大幅的提升了項目交付效率。c#

好了,廢話很少說,咱們進入正題。瀏覽器

什麼是ABP

ABP(ASP.NET Boilerplate)是一個開源的應用程序框架,以幫助開發人員快速開發。但它又不只僅是一個框架,更提供了一套基於DDD的架構模型和最佳實踐。緩存

快速示例

下面咱們來研究一個最簡單的示例來看看使用ABP有哪些好處架構

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

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

    [AbpAuthorize(MyPermissions.UpdateTasks)]
    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"));
        }

        input.MapTo(task);
    }
}

這裏咱們看到的是一個Application Service類, TaskAppService, 裏面定義了一個方法UpdateTask. Application Service在DDD的設計中是直接被展現層所調用的,簡單來講,一個前端頁面能夠直接調用TaskAppService.UpdateTask.app

就這個簡單的示例,咱們一塊兒來看看使用ABP有哪些好處。框架

  • 依賴注入 - ABP提供了一個慣用的DI基礎框架,所謂慣用,就是你們日常使用的DI方式一致,保持你們的使用習慣。由於這個示例是在應用服務層,因此注入容器中的實例生命週期都是短時的(每一個請求建立一次,生命週期與請求相同)。 它能夠簡單方便的注入任何依賴,好比在本示例中的IRepository
  • 倉儲 - ABP能夠爲每個實體都建立一個默認倉儲,在示例中是IRepository , 默認倉儲有許多很是有用的方法,例如示例中的FirstOrDefaultAsync, 而且咱們能夠很是容易的根據咱們本身需求來擴展倉儲。倉儲對DBMS和ORM作了抽象並簡化了數據訪問邏輯。
  • 受權- ABP可使用聲明式的方式來檢查權限。在示例中,若是一個用戶沒有登陸,或者沒有「UpdateTasks」的權限,那麼他將不能訪問UpdateTask方法。 ABP不僅僅使用聲明式的特性來檢查權限,它還提供了其餘的受權方式
  • 請求驗證- ABP自動的檢查請求輸入(input)是否爲null, 而且能夠基於標準的數據註解和自定義驗證規則來檢查輸入中的屬性是否合法。若是請求不合法,它將會拋出一個驗證異常。
  • 審計日誌- ABP會基於慣例和配置,自動爲每個請求記錄訪問的用戶、瀏覽器、IP地址、調用的服務、方法、參數、調用時間、耗時、和其它一些信息。
  • 工做單元- 在ABP中,每一個應用服務方法,都被默認視爲一個工做單元. 在進入方法時,ABP會自動的打開鏈接並開啓事務,若是方法在執行過程沒有任何異常,而且成功完成,那麼在退出方法時,ABP會自動提交事務並釋放鏈接。無論方法中使用了一個仍是多個倉儲,他們都是原子的,在一個事務中,全部的實體改變都會在事務提交時自動保存。正如示例中所示,咱們甚至都不用調用顯示的 '_repository.Update(task)'方法來保存數據更新。 不過我我的建議儘管能夠不顯示調用更新,可是從代碼的可讀性和可維護性仍是顯示的調用'_repository.Update(task)'方法
  • 異常處理- 在ABP咱們幾乎不用手動的來處理異常,ABP會默認自動處理全部異常。若是有異常發生,ABP會自動的記錄它,並返回合適的結果給客戶端。例如,若是這是一個AJAX請求,它會返回一個JSON對象給客戶端,並指明有一個錯誤發生。它會向客戶端隱藏真實的異常,除非咱們使用UserFriendlyException.
  • 日誌- 咱們可使用基類中定義的Logger對象來寫日誌。 ABP默認使用Log4Net來寫日誌,固然咱們也能夠經過修改配置來使用其餘的日誌框架。
  • 本地化(多語言)- 在示例中,當拋出異常時,使用了"L"方法,它會根據用戶文化配置自動進行本地化處理。
  • 自動映射- 在示例的最後一行,咱們使用了ABP的MapTo擴展方法來說輸入對象的屬性映射到實體對象的屬性。它使用了AutoMapper庫來執行映射,咱們能夠很容易的基於命名約定(簡單來說就是屬性名相同,固然也能夠指定)來將一個對象的屬性來映射到另外一個對象的屬性。一般不一樣層都會定義本身的數據對象模型,而在層與層之間進行數據交換時,就設計到不一樣數據對象的轉換,這個時候就是AutoMapper大顯身手的好時機。
  • 動態API層- TaskAppService只是一個通常的類,一般咱們須要寫一個Web API Controller包裝器來將TaskAppService的方法以API的形式暴露給客戶端調用,可是ABP在運行時已經自動爲AppService的方法生成了API接口,因此這樣看起來,就像是客戶端直接調用了AppService的方法(但實際不是)。
  • 動態Javascript AJAX代理- ABP在前端爲應用服務的調用建立了代理方法,這樣就能夠在前端像調用Javascript方法同樣調用應用服務。

在示例中,咱們能夠看到使用ABP的優點,一般若是咱們來作這些事情,會花費大量的時間,可是ABP框架都自動的爲咱們處理了。這裏必須點個讚了。async

此外,除了這個示例中展現的ABP的優點之外,ABP還提供了一個健壯的基礎架構和應用模型。包括模塊化、多租戶、緩存、配置管理、調度和後臺任務、數據過濾、領域時間、單元測試和集成測試等等。它讓咱們能夠集中關注在業務實現上,而不用重複的去造輪子。模塊化

相關文章
相關標籤/搜索