CUBA與Spring相比,有很大的不同嗎?


原文:Developing with CUBA - a big shift from Spring?

翻譯:CUBA China                                                         

CUBA-Platform 官網 : https://www.cuba-platform.com

CUBA China 官網 : http://cuba-platform.cn

歡迎轉載,轉載請注明來源。

 

  企業級軟件開發人員通常會面對如下需求組合(至少我經常遇到的是):設計優良的數據存儲結構(有時候是已有的舊數據庫模型),大量的數據錄入表單,非常復雜的業務邏輯、報表功能、與許多公司其他系統(財會、CRM等)集成,數千並發量。對此,你首先考慮的是什么?

  “首先,采用主流的關系數據數據庫管理(RDBMS)、Hibernate / JPA + Spring Boot、REST API,並且使用我最喜歡的或者最新的JS框架來實現UI。”

  “嗯~,還需配置Spring Security ,也許還需要寫一部分代碼來實現行級別的數據保護功能。如何實現呢?也許會用到數據庫視圖或虛擬專用數據庫。“

  “所有這些DAO代碼都非常相似且枯燥,但我還是需要一一實現。”

  “可以使用類似ModelMapper的東西將JPA實體轉換為REST的DTO。”

  “別忘了跟實習生強調下懶加載和JPA關聯查詢。”

  “唉,其實都是雷同登錄界面、千篇一律的實體到DTO的轉換,有沒有辦法能讓我擺脫所有這些乏味的東西 ,只需要專注於關鍵的業務邏輯實現呢?”

       本文適合使用Spring框架(包括Spring Boot)從頭開始做過幾個項目、並且正在考慮怎么提高自己工作效率的開發人員。在文章中,我將向您展示如何使用CUBA平台擺脫常見的耗時枯燥任務。

 

又一個框架?

 

  開發人員在聽到新框架時提出的第一個問題往往是:“為什么我需要這個?Spring Boot就能很好地幫助我從頭開始實現所有內容”。 沒錯,新平台意味着新的規則、新的限制,之前積累的其他框架的經驗便失去了意義。就算是目前使用的框架不完美,但是對它足夠了解,知道有哪些坑,和哪些變通的方法。

  但是,從Spring切換到CUBA,並不需要重頭學習規則,甚至沒有什么變化,只要稍微前進一步就可以擺脫枯燥的開發任務,擺脫數百行DTO架子代碼和轉換工具的困擾,擺脫實現數據分頁或數據過濾組件、創建Spring Security配置文件(JPA,Cache,...)等等些基礎功能的麻煩。

  本文中,我們將從頭開始展示CUBA如何遵循幾乎所有基於Spring的開發模式,開發人員在Spring中積累的經驗能被充分利用,同樣的研發投入卻能交付更多。為了使情景更清晰簡潔,本文側重於后端代碼。

 

Spring應用程序架構

  Spring應用程序的典型架構可以很容易搜索到,很多情況下,它可以表示為具有一些交叉區域的典型三層應用程序。讓我們來看看“經典”的Spring應用程序:

 

  領域模型(Domain Model) - 通常需要手動創建。但是,有一些工具可基於數據存儲結構創建領域模型。

  數據存儲層(Repository Layer) - 與數據存儲一起使用的類。也稱為“DAO”,“存儲庫(Repositories)”等。這塊是ORM框架(及其兄弟姐妹們)的領地。它通常包含功能域模型中的一個實體執行CRUD操作的類。

  服務層(Service Layer) - 有時開發人員會創建一個額外的層來分離業務邏輯和數據CRUD操作。如果項目業務邏輯復雜,涉及不同類型的數據源,或者涉及外部服務集成,這一層會很有用。

  Web /控制器層(REST / MVC) - 用來處理REST API(將由基於瀏覽器的應用程序使用)或使用JSP實現的視圖,或是模板框架(thymeleaf, velocity)、JVM前端框架(GWT, Vaadin,Wicket等)。由於API結構或前端界面展示不同,通常控制器是操作DTO而不是實體對象。因此,開發人員通常必須在實體模型和DTO模型之間實現雙向轉換。

 

  如果您對以上描述很熟悉(甚至覺得是顯而易見 - 那么恭喜,您可以毫無障礙地開始使用CUBA。

 

參考應用 - 寵物診所

  話不多說,接下來看code怎么寫。在GitHub上,有一個眾所周知的Spring的“參考”應用程序 - Pet Clinic(寵物診所)。下面我們將展示如何使用你的Spring技能加上CUBA框架開發一個新的寵物診所程序。Antoine Rey的參考程序有非常好的、詳細的說明; 我們將在本文中重復一些內容。

 

數據模型

  圖中顯示了數據庫的ER圖。應用程序代碼中實際的對象域模型有點復雜並且包含一些繼承,您可以在上面提到的演示文稿中找到UML模型。

存儲層

  有四個Repository來處理主要實體:Owner(主人),Pet(寵物),Visit(拜訪)和Vet(獸醫)。這些Repository基於Spring JPA框架,由於Spring JPA的特性,這些Repository幾乎不包含什么代碼,但在Owner Repository里面有一個自定義的查詢,用來獲取寵物主人和他們各自的寵物。

UI界面

  該應用程序包含九個界面,我們可以通過這些界面查看數據,並進行一些編輯:寵物主人,寵物和拜訪。本文不討論它們,但需要指出的是,這些界面都是面向數據的應用程序里常見的CRUD表單。

附加功能

  除了簡單的CRUD功能外,該應用程序還包括一些能展示Spring Framework之強大的功能:

  l 緩存(Caching) - 獸醫列表已緩存,因此在刷新獸醫列表時不會有DB讀取。

  l 驗證器(Validator) - 檢查在創建有關寵物的新記錄時是否填寫了所有字段。

  l 格式化程序(Formatter) - 用於正確顯示寵物類型。

  l 多語言支持(i18n) - 該應用程序提供英語和德語版本。

  l 事務管理 - 某些數據庫查詢是只讀的。

感想

 

  我非常喜歡這張圖片,因為它精准表達了我的看法:要有效地使用任何框架,都需要了解它內部的工作原理。例如,Spring Boot隱藏了很多東西,如果你知道一個簡單的JPA接口初始化背后有多少個類,你會嚇一跳。以下是關於Spring Boot Pet Clinic應用程序中“神奇”的部分:

  l @Caсheable - 除了這個注解之外沒有任何緩存配置代碼,但Spring Boot“知道”如何設置緩存實現(在我們的例子中將是EhCache)。

  l @Transactional -  Repository沒有這個注解(它們的父類org.springframework.data.repository.Repository也沒有),但所有save()方法都可以正常工作。

  雖然存在這么多隱晦的地方,但是由於Spring Boot的透明性和可預測性,Spring Boot還是一個非常流行的框架。Spring Boot還有非常詳細的文檔,而且是開源的,所以你可以深入研究它的原理和任何方法的實現,研究里面的邏輯。我想每個人都喜歡透明且易於管理的框架,因為它們可以使您的應用程序更加易於維護。

寵物診所與CUBA

  現在,讓我們看看使用CUBA平台的Pet Clinic,根據我們的Spring知識來審視它,並找出我們都能在哪些地方節約開發時間。

  在GitHub上可以找到Pet Clinic實現的源代碼CUBA平台有非常好的文檔,其中可以找到幾乎有關CUBA的所有東西(大多數情況都有代碼段或者代碼實例,都能在GitHub上找到)。在本文中,我們將更多的引用CUBA文檔,以避免重復描述。

 

CUBA應用程序架構

                         

  CUBA應用程序包含以下模塊(請參見圖表)。

  l Global - 包含可以在其他模塊中使用的數據庫實體、CUBA視圖和服務接口。

  l Core - 所有與數據庫一起工作並實現業務邏輯的服務實現都應該放在這里。需要注意的是,Core模塊里面的類在其他模塊中並不可用,這樣設計的目的是,可以獨立部署Core和GUI模塊到不同的服務器,給系統提供了很好的可擴展性。而想要將Core模塊的服務注入其他模塊,您應該使用Global模塊中聲明的接口。

  l GUI,Web,Desktop,Portal - 這些模塊包含負責UI事件處理的GUI相關類(控制器,監聽器等)。您可以在此處創建自定義REST控制器,以補全CUBA為您生成開箱即用的REST API

  為了提高開發人員效率,CUBA提供了Studio - 一個漂亮小巧的圖形化工具,用於創建和注冊實體,並且可以為您更新所有配置,幫助創建服務的架子代碼,並具有功能界面的可視化編輯器。

  因此,基於CUBA平台的應用程序包含兩個(或更多)單獨的模塊:可以單獨部署的Core和GUI,以及一個跨功能域的Global模塊。下面我們詳細介紹一下CUBA的GlobalCore模塊及其內容。

Global模塊

實體模型(Entity Model)

  任何使用過與JPA標准兼容的ORM框架或者Spring的開發人員都應該熟悉CUBA應用程序中的實體模型。同樣是用@Table,@Entity等注釋的類,並在persistence.xml文件中注冊。

  在Pet Clinic應用程序的實體模型中,您可以重用Spring版本中的代碼,但您需要記住以下幾點:

  1. CUBA 為使用此平台創建的每個組件Component)引入了一個“命名空間”,以防止不同組件之間的名稱沖突。這就是為什么每個實體名稱都有一個“petclinic$”前綴。

  2. 建議對實體使用@NamePattern注釋,這樣在界面可以得到實體更有意義命名。

  問題是,除了前綴和聲明實體的“字符串式”表示之外,CUBA還提供了什么其他功能?其他功能包括:

  1. 支持ID生成功能的基類:從整數ID到UUID

  2. 一組有用(但可選)的接口:

    l Versioned - 支持實體版本。

    l SoftDelete - 支持實體的“軟”刪除,或者說是“邏輯”刪除。

    l Updatable - 添加實體更新日志記錄的字段。

    l Creatable - 添加實體創建日志記錄的字段。

    您可以在文檔閱讀有關這些接口的更多信息。

  3. CUBA Studio可以自動生成數據庫創建和更新腳本。

  在應用程序開發期間,我只是從Spring版本復制了現有實體模型,並添加了上面提到的CUBA特定功能,從程序的參考版本中刪除了BaseEntity類。

視圖(Views)

  CUBA的“視圖”概念可能令人困惑,但很容易解釋。視圖是一種聲明性方法,用於指定應提取哪些數據(屬性和嵌套實例/集合)。

  讓我們假設您需要獲取Owner及其寵物或獸醫的屬性 - 用於在同一個界面上顯示依賴的子實體和父實體。在純Spring實現的情況下,您需要定義JPA關聯查詢:

  @Query("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id") public Owner findById(@Param("id") int id);

  ...或定義正確的EAGER / LAZY FETCH類型以獲取事務上下文中的實體的依賴集合。

  @ManyToMany(fetch = FetchType.EAGER) @JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"), inverseJoinColumns = @JoinColumn(name = "specialty_id")) private Set specialties;

  在CUBA版本中,您可以使用EntityManager和JPQL或視圖和DataManager:

  1. 定義一個指定我們想要提取的內容的視圖:

  

  2. 使用DataManager bean獲取此數據

  

 

  您可以為不同的任務創建不同的視圖,選擇要獲取的屬性,是否獲取集合以及定義對象樹的深度。在Mario David的博客中有一篇關於視圖的精彩文章

  在寵物診所程序中,我們為不同的場景定義了六個視圖。這些視圖主要用於UI表單,其中之一是在服務中用來獲取數據,上面顯示了這個代碼片段。

服務接口

  由於Global模塊在CUBA的應用程序架構中屬於交叉支撐的模塊,因此您應該把服務的接口定義在Global模塊中,以便能夠通過使用Spring的注入在其他模塊中使用服務。您需要做的就是在Web模塊的“web-spring.xml”文件中注冊服務。CUBA平台在應用程序模塊中創建代理,采用Spring配置XML文件的方法進行完全透明的實體序列化和反序列化。此功能使我們可以從其他模塊調用Core模塊中實現的服務,即使在分布式部署的情況下也只需要很少的額外工作。

  因此,在使用CUBA進行實體模型開發方面,它與純Spring完全相同,但是在插入數據后你不需要關心實體和關聯實體的ID是怎么生成的,也不需要寫額外的代碼去實現實體版本化,軟刪除和實體變更日志。相比較於JPA關聯查詢,您還可以利用創建CUBA視圖來節省一些時間。

Core模塊

  在Global模塊中聲明的服務接口都在Core模塊實現。一般來說,CUBA應用程序中的每個服務都使用@Service注解,但您可以使用所有Spring里面可用的注解來處理bean。不過,由於CUBA的特殊架構,存在一些限制:

  l 如果希望在Web模塊中使用服務,則需要使用@Service做服務注解。

  l 建議為服務創建服務名,以避免不同加載項中的Bean命名沖突。

  除此之外,您的Core模塊代碼庫是一個“純粹的”基於Spring的后端應用程序。您可以使用與以前相同的方式從數據存儲中獲取數據,調用第三方Web service等。唯一重要的區別是與數據庫的交互:

  EntityManager和DataManager

  CUBA平台使用自己的EntityManager,將其部分功能委托給實際的javax.persistence.EntityManager實例。CUBA的EntityManager主要提供低級別實體操作,不支持安全功能。所以在大多數情況下,還是推薦使用提供額外功能的DataManager

  1. 行級和屬性級安全性支持。

  2. 可以采用CUBA的實體視圖獲取數據。

  3. 支持動態屬性

  有關DataManager和EntityManager的更多信息,請參閱文檔。值得注意的是,您不需要在GUI中直接使用這些bean,而可以使用數據源

  順便談談PetClinic - 我(幾乎)沒有在Core模塊中編寫很多代碼,因為沒有特別復雜的業務邏輯。

CUBA實現的Spring寵物診所的功能

  在上一節中,基於Spring的Pet Clinic應用程序中我們總結了一個額外功能列表,CUBA中也提供了相同的功能:

緩存(Caching

  CUBA原生支持實體和查詢緩存。這些緩存在文檔中有詳細描述,在使用時應首先考慮,因為它們支持分布式部署等所有平台功能。除此之外,您還可以使用Spring的@Cacheable啟用緩存,並啟用Spring 文檔中所述的cach provider。

驗證器(Validator

  CUBA使用BeanValidation作為標准驗證引擎。如果內置驗證不夠,您可以定義自定義驗證代碼。而且還可以通過描述定義Validator類來提供驗證UI數據的選項在這里

格式化(Formatter

  CUBA平台為GUI組件提供了幾種格式化程序,但除標准格式化程序外,您還可以定義自己的格式化程序。對於默認實體命名的格式化,使用@NamePattern注釋。

國際化(I18n

  CUBA平台支持國際化的方式與其他java應用程序相同:使用message.properties文件,所以這里沒什么新東西。

事務管理

  CUBA平台提供以下事務管理選項:

  l 熟悉的Spring @Transactional注釋

  l 如果在某些復雜情況下需要細粒度的事務管理,那么可以采用CUBA的持久層接口。

  當我開發寵物診所時,我只考慮過一次事:那就是在開發允許編輯Owner、Pet以及在同一屏幕上添加Visit的表單的時候。此時我需要了解何時提交事務並刷新界面然后統一的顯示數據。

真的幾個小時就完成了寵物診所

  我能夠在不到一天的時間內使用“標准”CUBA UI創建一個與Spring的Pet Clinic具有相同功能的應用程序。我不會說我是CUBA的專家(自我開始以來僅僅幾周),但我有很長的時間在使用Spring。腦海中回想一下Spring程序的架構,然后我們看一下基於CUBA的架構:

  l 領域模型 - Global模塊中的實體。創建實體模型是每個程序中都需要的過程。由於使用BaseIntegerIdEntity類,在ID生成方面可以節省時間。

  l 數據存儲層 - 我不需要Repository,甚至連一個接口也不需要。我只是使用CUBA Studio 創建了一些視圖。通過使用這個工具,我也不需要在配置文件中編寫XML。

  l 服務層 - 在我們的應用程序中,我們只有兩個服務用來導出JSON和XML格式的Vets,這些Vets是可緩存的。我根據文檔將接口放到Global模塊,將接口實現放到Core模塊。除了閱讀有關DataManager以熟悉其API之外,這基本只是一個“正常”的開發過程。

  l 控制器層 - CUBA Pet Clinic在Web模塊中僅包含一個用於JSON和XML feed的自定義的REST控制器。這里沒有特別要說的,只是一個采用了Spring注解的控制器。

  l 應用程序GUI - 使用CUBA Studio創建“標准”CRUD表單非常簡單。

    在實現的過程中,我完全沒有考慮如何將實體傳遞給Web UI,也沒有考慮表單提交,也沒有相關的控制器和Repository。CUBA為我提供了界面上一個比較好用的表格組件以及一個數據過濾組件,因此我不再需要解析查詢語句,也不需要特意做分頁。我花了大部分時間來實現界面的流程流轉,以及調整頁面樣式。

  我的個人體驗如下表所示:

 

 

CUBA中易於理解的部分

CUBA中需要閱讀文檔的部分

實體

實體建模

數據庫創建腳本

標准基類

軟刪除等的附加功能

EntityManager

視圖

DataManager

服務

Bean管理

事務管理

安全性和用戶管理

持久層接口

控制器

自定義REST控制器

請求URL映射

服務方法發布

UI

標准表格

自定義UI

  顯然Pet Clinic程序沒有使用所有CUBA提供的特性,可以在站點上找到CUBA特性的完整列表,這里可以看到該平台可以怎樣解決其他的一些常見任務。

  我的個人觀點 - 如果您使用企業軟件的標准界面,CUBA可以簡化后端實施並做得很好。如果你需要一個精美的界面,那么CUBA也會幫你節省在后端開發上的時間。

這么多優點!有沒有什么缺點?

  好吧,我想在本節中提到一些問題,這些問題的存在不影響使用CUBA,但是我發現這些問題會給第一次接觸CUBA的人帶來不好印象:

  l 在介紹部分,CUBA平台說自己帶有IDE,能簡化項目的創建和管理。但有時在Studio和IDE之間切換可能會有點煩人。CUBA平台現在正在重新開發它,因此Studio很快就會轉變為IDEA的插件。

  l CUBA中,我們使用了比典型的Spring Boot應用程序更多的XML配置文件,因為平台提供的服務更多,各個模塊之間需要一些XML來作為連接。

  l 應用程序的單個頁面都沒有“友好”的URL。您可以使用屏幕鏈接直接訪問屏幕,但這也非常不直觀。

  l 您必須處理CUBA的DataManager和EntityManager並學習它們的API而不是Spring JPA或JDBC(但如果需要,仍然可以使用它們)。

  l 使用關系數據庫時,使用CUBA將達到開發的最佳效率。而如果要使用NoSQL,CUBA的表現和Spring一樣,都有很多需要自己寫代碼的地方。

結論

  如果您有一個需要以關系型數據庫作為數據儲存,並且以數據為中心的應用程序的需求,您可能需要嘗試使用CUBA平台作為基礎來開發,因為:

  1. CUBA是透明的。源代碼可用,您可以調試所有內容。

  2. CUBA很靈活(但是也有一定限度)。您可以繼承並注入自己的bean而不采用標准CUBA bean,也可以發布自定義REST API並使用您自己的前端框架實現與用戶交互。

  3. CUBA就是Spring。80%的后端代碼都是純Spring應用程序。

  4. 使用CUBA可以加快項目啟動。在第一個實體和UI屏幕創建之后,應用程序就可以使用了。

  5. CUBA為您完成了很多日常枯燥的工作。

  因此,通過使用CUBA,您將在枯燥的工作上節省不少時間,以便真正投入地處理復雜的業務相關邏輯,也可以實現與其他系統的無縫集成。

鏈接

CUBA-Platform 官網 :

     https://www.cuba-platform.com

CUBA China 官網 :

  http://cuba-platform.cn


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM