運行時目錄以及Moqui的xml配置文件
Moqui框架部署運行主要有三個核心部分:
可執行的war包文件
運行時目錄
Moqui配置文件XML格式
不管怎么使用這個可執行的war文件,你必須擁有一個運行時的目錄,同時你也許會重寫Moqui默認配置文件MoquiDefaultConf.xml里的配置信息,例如在運行時目錄或者conf目錄中的MoquiProductionConf.xml文件里面重寫。
運行時目錄主要防止的是你想要的組建/應用系統的入口文件以及配置文件。同時,框架會在這個目錄下存放日志文件,Derby數據庫文件。
運行時,需要指定如下兩個屬性:


可執行的WAR文件:




運行時配置moqui.runtime和moqui.conf屬性的例子來源於編譯路徑下的MoquiInit.properties文件/


在WAR文件中內嵌運行時目錄:
Moqui框架能夠運行加載一個外部的運行時目錄,也支持運行時目錄打包在WAR文件內部的方式。內嵌的方式特別適用於類似Amazon ElasticBeanstalk這種WAR部署方式的容器。創建一個內嵌運行時目錄的WAR文件:


編譯Moqui框架:
使用自動編譯工具Gradle去編譯源碼


在gradle里面,加載load和運行run都依賴於構建build任務。由於這種依賴存在。最簡單的方式去在一個流行的數據庫上創建一個新的開發環境可以通過執行這個命令:$gradle load run
數據庫配置:
數據庫的安裝配置已經在Moqui框架的XML配置文件的moqui-conf.entity-facade.datasource元素中完成。這里有個元素用來為每個實體分組使用,並且datasource.group-name屬性與entity.group-name屬性想對應匹配
默認的Apache Derby數據庫配置:


Moqui代碼中一些常用的表達式:


作為web請求(HttpServletRequest)的一部分,一個創建的ExecutionContext實例有一個特殊的門面叫做web門面。這個門面用於訪問上下文的servlet環境信息,包括請求,響應,繪畫以及應用(ServletContext).它同樣用於訪問servlet環境中各個部分的狀態(屬性),包括請求參數,請求屬性,會話屬性和應用屬性。
web參數:
請求參數“map”(ec.web.request.Parameters)是一個特別的map,它包含了源於URL參數字符串的承諾書,內聯URL參數,以及源自提交的多個部分。這里還有個特殊的參數,ap(ec.web.parameters),它按照以下的順序將所有的map組合在一起:請求參數,應用屬性,回話屬性和請求屬性。參數map類似於上下文是一個請求屬性map的棧,所以如果你要對其進行寫入,數值將會放在棧的頂部。
為了安全的因素,請求參數map使用OWASP WSAPI類庫進行規范化轉換以及過濾。它和服務門面校驗一起有助於防止跨站腳本攻擊(XSS)和注入攻擊。


工廠,Servlet&監聽器:
執行上下文實例通過執行上下文工廠(Execution Context Factory)進行創建,當有需要的時候可以直接通過編碼的方式直接其創建,但通常都是通過Moqui框架鎖運行的容器去創建。
在部署Moqui項目的時候。Moqui的跟web應用都會被加載,冰球WEB-INF目錄下的web.xml文件會告訴你servlet容器去加載MoquiServlet MoquiSessionListener 和MoquiContextListener。這些都是框架中包含的末人類,並且如果要改變ExecutionContextFactory和ExecutionContext的生命周期,可以創建自己的類。
MoquiContextListener在contextInitialized()事件中創建了ExecutionContextFactory對象,並在contextDestroyed()事件中銷毀它/MoquiServlet的工廠為每個請求在doGet()和doPost()方法中創建了ExecutionContext對象,同時在每個請求的最后,使用相同的方法去銷毀這個對象。
資源和緩存門面:
資源門面用於訪問和執行資源。例如腳本,模板和內容。緩存門面用於緩存上的常規操作,並作為一個緩存Cache接口的實現去獲取一個緩存的屬性。與支持的基本get/put/remove等操作在一起,你可以獲得每個緩存的統計以及修改緩存的屬性,例如超時,大小限制以及清理算法。默認的緩存界面實現就是ehcache的一個封裝,除了在MoquiXML配置文件中隊緩存門面進行配置,你可以使用ehcache.xml文件進行額外的配置選項。
資源門面使用緩存門面按照文件源的位置(通過getLocationText()方法獲得)去獲得緩存純文本,通過路徑位置去編譯Grovvy和XML動作腳本(使用runScriptCurrentContext里的方法),以及同樣通過路徑位置去編譯FreeMaker(FTL)模板(通過readerTemplateCurrentContext()方法)。
同樣有緩存用於貫穿在界面XML和表單定義中的分散的小型Groovy表達式,冰球緩存以表達式實際的文本作為鍵而不是表達式來源的位置(通過evaluateCondition(),evaluateContextField()和evaluateStringExpand()方法)。
為了更通用的資源訪問,getLocationReference()方法返回一個ResourceReference接口的實現。它可以用於讀取資源內容(包括文件和目錄),並獲得關於內容類型,最后修改時間及其所在的位置等信息。框架生育的部分使用這些資源引用以一種通用的擴展的方式去訪問資源。ResourceReference接口可以按需進行實現,並且一存在的默認實現包含了后面的協議/體制:http https file ftp jar classpath component以及content。
界面門面:
界面門面的API主要就是充當了ScreenRender接口實現的工廠。通過ScreenRender接口你可以在各種上下文中渲染界面,最常見的就是在服務中不依賴Servlet容器進行渲染,或使用便利的ScreenRender.render(request,response)方法在響應一個HttpServletRequest請求時進行呈現。
通常進行渲染時,將指定根界面的位置來渲染根界面,同時可選的指定一個子界面路徑去渲染自界面。對於web請求來說,自界面的路徑就是簡單的pathinfo請求
界面定義:
在界面定義的XML文件中。每個界面都可以指定web設置,參數,響應轉換,子界面,展現前動作以及部件。部件包括子界面菜單/激活/面板。截面,rom后期,容器面板,指定渲染式模式的內容(html xml csv text xsl-fo等)以及表單。
表單分為:單個表單和列表表單。雖然界面表單主要定義在界面XML中,但是他們同樣也可以使用DbForm和關聯實體去為不同的用戶組進行擴展。
基於服務auto-fields-service元素的表單非常重要的一點是,各種客戶端的校驗基於服務中與表單字段相關的校驗定義,將會被自動的添加。
界面/表單渲染模板
ScreenReader的輸出,通過為界面和表單定義的XML元素而運行的宏定義模板創建。如果模板是通過ScreenReader.macroTemplate()方法指定的,那么他將會被使用,否則模板的呈現將決定於渲染模式renderMode,以及Moqui XML配置文件中的screen-facade.screen-text-output元素配置。你可以創建自己的模板去覆蓋默認模板或簡單的忽略他們,同時在Moqui XML配置文件中配置他們來獲得你想要的輸出
服務門面:
服務門面通過大量的同步的,異步的,計划的以及特殊的服務調用接口取調用服務。
服務命名:
服務命名由三部分組成:路徑,動詞和名詞。當引用一個服務時,他們的組合形式為:"${path}.${verb}#${noun}",路徑應當是一個java包分割的路徑,例如org.moqui.impl.UserServices指的就是文件classpath://service/org/moqui/impl/UserServices/xml.雖然指定路徑的方式有點不方便,但是它更易於去組織服務,基於服務的調用去找到定義,並提供性能以及進行緩存(懶加載)
服務定義文件將會給予框架的位置模式路勁被查找到:"classpath://service/$1"和"component://.*/service/$1"這里的$1就是路徑,"."會被轉換為'/',同時在路徑的最后加上".xml"
服務名稱的動詞(必須項)和名稱(可選項)部分分割開來是為了跟呵呵的描述服務做什么和服務執行在哪個實體上
服務門面唯一的基於實體定義支持CrUD操作。使用這些實體隱士服務需要使用由一個無路徑的,一個增加/修改/刪除的名詞,一個哈希(#)標識,以及實體的名字鎖組成的服務名稱。例如更新一條UserAccount的記錄使用的服務名稱為update#UserAccount。當定義實體自動entity-auto服務時,名詞必須為實體的名稱,同時服務門面將會使用出入參及實體定義去覺得做什么
完整服務的名稱:org.moqui.impl.UserServices.update#UserAccount
實體門面:
用於普通的數據庫交互,包括新增/修改/刪除以及查找操作,以及用於更專門的操作,如加載和創建視圖XML數據文件。。
雖然 這些操作 是通用 的並覆蓋了 典型 應用中大 部分的數據庫交互需求 ,但有時 ,你需要底層訪問 你可以通過 你可以通過 Moqui XML配置文件中 基於 entity facade數據庫配置 的實體門面來獲得一個 獲得一個 JDBC連接對象。
屍體相當於數據庫中的表,並主要被定義在XML文件中。這些定義包含了羅列實體中的字段,實體間的關系,指定索引等。實體可以使用UserField及其關聯實體的數據庫記錄來進行擴展。
每天單條記錄都通過EntityValue接口的實例來表現。這個接口為了方便起見擴展了M ap的接口,同時添加了額外的方法用於獲得指定的數據集合,例如主鍵值。接口通用有用於數據庫交互的方法對指定記錄進行增刪改查,獲取/設置主/次要序列ID值,以及基於實體定義里的關聯關系去查找關聯記錄。使用EntityFacade.makeValue()方法去創建一條新的EntityValue對象,大部分的時候會通過查詢獲得EntityValue實例。
使用EntityValue接口進行實體記錄的查詢。通過EntityFacade.makeFind()方法獲得這個接口的實例。這個查詢接口允許為查詢設置各種的條件(用於where和having關鍵字,更多邊界的方法用於where)指定選擇的字段和排序字段,設置偏移和限制數值,以及包括使用緩存,更新及去重的標記。一旦操作設置完成,你就可以調用方法進行實際的欻性能,包括one() list() iterator() count() updateAll()以及deleteAll()
多租戶:
當從執行上下文ExecutionContext中獲得一個實體門面EntityFacade實例時,這個重新取回的實例將會用於當前上下文ExecutionContext(它將在指定的用戶認證之前或通過servlet,亦或是請求執行前的監聽器去進行設置)中活躍的租戶tenantld如果沒有tenantld實體門面EntityFacade江湖用於默認的DEFAULT租戶使用MoquiXML配置文件中的設置,否則,它將會使用活躍的tenantld去查找Tenant*實體上的設置,去覆蓋MoquiXML配置文件中默認的數據源設置。
連接池和數據庫
實體門面使用Atomikos TransactionsEssentials或Bitronix BTM用於XA-aware數據庫連接池。使用jta.properties文件去配置Atomikos,bitronix-default-config-properties文件去配置Bitronix。通過Moqui XML配置文件中entity-facade元素的配置,你可以修改默認的連接池並使用任何的DataSource或替代的JNDI XADataSource
Moqui框架中包含的默認數據庫是Apache Derby。它很容易通過Moqui XML配置文件中entity-facade元素的配置去改變。添加一個新的database-list.database元素可以新增一個在MoquiDefaultConf.xml文件中尚不支持的數據庫。當前默認支持的數據庫包括Apache Derby ..DB2 HSQL MySql Postgres Oracle以及MS SQL Server.
數據庫元數據:
事物門面:
食物主要用於服務和界面。服務定義上有事物設置,基於此服務調用者可以按需去暫停/回復以及開始/提交/回滾事務。對於界面來說,事務總是開始於轉換,並用於渲染實際的界面,事務僅胡開始與如果界面設置使用了事務。
也可以使用事務門面TransactionFacade去手動划分事務姐main。JavaDoc文檔中有一些推薦模式的代碼樣例使用了try/catch/finally自居去開始/提交/回滾以及暫停恢復事務,來確保事務被合理的管理。
當調試事務的問題時。例如會追蹤一個僅回滾的設置在何處,事務門面TransactionFacade同樣可以使用,因為當調用setRollbackOnly()方法時事務門面保持了一盒追蹤堆棧。它將在售后的錯誤中自動進行日志記錄,同時也可以在其他時間手動的去獲得這些日志記錄信息。
事務管理JTA
事務門面默認使用Bitronix TM類庫。使用bitronix-default-config.properties文件配置Bitronix.Moqui框架同樣開箱即用的支持Atomikos,通過jta.properties文件配置
任何例如來源於應用服務器的一個JTA事務管理,可用於替代配置與Moqui XML配置文件里entity-facade元素中UserTransaction和TransactionManager實現的JNDI方式。
構件執行門面
被其他門面所調用,用於保持追蹤執行上下文ExecutionContext聲明周期中哪些構件正在運行。它保持了所有構件的一個歷史遺跡當前運行構件的一個堆棧。力圖:如果一個界面調用了一個自界面,同時自界面調用了一個實體查詢的服務,堆棧將為第一個界面,然后是第二個界面,接着是服務,最后是實體。