請熟悉基本的AEM Project Archetype use和FileVault Content Maven Plug-in,因為本文章以這些學習和概念為基礎。
本文概述Adobe Experience Manager Maven專案在AEM與雲端服務相容時所需的變更,確保這些專案遵守可變和不可變內容的分割,建立相依性以建立不衝突、確定性的部署,並封裝成可部署結構。
AEM應用程式部署必須由單一AEM套件組成。 此套件應包含子套件,這些子套件包含應用程式運作所需的一切,包括程式碼、組態和任何支援的基準內容。
AEM需要分離內 容和程式碼 ,這表示單一內容套件 無法部署至 /apps
Runtime可寫區域 (例如,可寫區域)。/content
、 /conf
、 /home
或其他非 /apps
)。而應用程式必須將程式碼和內容分隔為獨立套件,以便部署至AEM。
本檔案中概述的套件結構與本機開 發部署 和AEM cloud服務部署都相容。
本檔案中概述的組態由AEM Project Maven Archetype 24或更新版本提供。
/apps
and /libs
are consed inmumable areas of AEM as they cannot be changed(create, update, delete)after AEM starts(i.e. at runtime)。在運行時更改不可變區域的任何嘗試都將失敗。
儲存庫中的其它所有內容,如/content
、/conf
、/var
、/etc
、/oak:index
、/system
、/tmp
等。 皆為mutable區域,這表示這些區域可在執行時期變更。
和舊版AEM一樣,/libs
不應加以修改。 只有AEM產品代碼可部署至/libs
。
Oak索引(/oak:index
)由AEM特別管理為雲端服務部署程式。 這是因為Cloud Manager必須等到部署任何新索引並完全重新建立索引後,才能切換到新的代碼映像。
因此,雖然Oak索引在運行時是可變的,但必須將其部署為代碼,以便在安裝任何可變軟體包之前安裝它們。 因此,/oak:index
組態是程式碼套件的一部分,而不是內容套件的一部分,如下所述。
如需在AEM中以Cloud Service建立索引的詳細資訊,請參閱檔案內容搜尋與索引。
此圖概述了建議的項目結構和包部署對象。
建議的應用程式部署結構如下:
將生成OSGi捆綁Jar檔案,並直接嵌入到所有項目中。
ui.apps
軟體包包含要部署的所有代碼,並僅部署到/apps
。 ui.apps
軟體包的常見元素包括,但不限於:
ui.config
軟體包包含所有OSGi配置:
/apps/my-app/osgiconfig
/apps/my-app/osgiconfig/config
/apps/my-app/osgiconfig/config.<author|publish>.<dev|stage|prod>
config.<runmode>
資料夾中,並用於定義:
ui.content
套件包含所有內容和設定。 「內容套件」包含ui.apps
或ui.config
套件中未包含的所有節點定義,換言之,包含/apps
或/oak:index
中未包含的任何內容。 ui.content
軟體包的常見元素包括,但不限於:
/conf
/content
、 /content/dam
等。/content/cq:tags
/etc
all
套件是容器套件,僅包含可部署的工件、OSGI套件Jar檔案、ui.apps
、ui.config
和ui.content
套件。 all
軟體包不得具有任何內容或代碼,而是將所有部署到儲存庫的子軟體包或OSGi包Jar檔案。
現在,軟體包是使用Maven FileVault Package Maven插件的嵌入式配置而不是<subPackages>
配置來包含的。
對於複雜的Experience Manager部署,可能需要在AEM中建立多個ui.apps
、ui.config
和ui.content
專案/套件,以代表特定網站或租戶。 如果完成此操作,請確保可變內容和不可變內容之間的分割得到尊重,並且所需的內容包和OSGi捆綁Jar檔案將作為子包嵌入all
容器內容包中。
例如,複雜的部署內容套件結構可能如下所示:
all
內容套件內嵌下列套件,以建立單一部署工件
common.ui.apps
部署站點A和站 點B所需的代碼site-a.core
站點A需要的OSGi捆綁Jarsite-a.ui.apps
部署站點A所需的代碼site-a.ui.config
部署站點A所需的OSGi配置site-a.ui.content
部署站點A所需的內容和配置site-b.core
站點B需要的OSGi捆綁Jarsite-b.ui.apps
部署站點B所需的代碼site-b.ui.config
部署站點B所需的OSGi配置site-b.ui.content
部署站點B所需的內容和配置如果AEM部署使用其他AEM專案,而這些專案本身也由其自己的程式碼和內容套件組成,則其容器套件應內嵌在專案的all
套件中。
例如,包含2個廠商AEM應用程式的AEM專案可能如下所示:
all
內容套件內嵌下列套件,以建立單一部署工件
core
AEM應用程式需要的OSGi Bundle Jarui.apps
部署AEM應用程式所需的程式碼ui.config
部署AEM應用程式所需的OSGi組態ui.content
部署AEM應用程式所需的內容和設定vendor-x.all
部署供應商X應用程式所需的一切(程式碼和內容)vendor-y.all
部署供應商Y應用程式所需的一切(程式碼和內容)包將用其聲明的包類型標籤。
packageType
設為container
。packageType
設定為application
。packageType
設定為content
。如需詳細資訊,請參閱下方的Apache Jackrabbit FileVault - Package Maven Plugin檔案和FileVault Maven組態程式碼片段。
有關完整的程式碼片段,請參閱下面的POM XML程式碼片段一節。
依預設,Adobe Cloud manager會收集由Maven組建版本產生的所有套件,但是,由於容器(all
)套件是包含所有程式碼和內容套件的單一部署工件,因此我們必須確保僅部署容器( all
)套件。為確保此,Maven構建版本生成的其他軟體包必須用的FileVault Content Package Maven插件配置進行標籤 <properties><cloudManagerTarget>none</cloudManageTarget></properties>
。
有關完整的程式碼片段,請參閱下面的POM XML程式碼片段一節。
Repo Init提供了定義JCR結構的指令或指令碼,這些結構從常見的節點結構(如資料夾樹)到用戶、服務用戶、組和ACL定義。
回購初始化的主要優點是,它們具有執行其指令碼定義的所有操作的隱式權限,並且在部署生命週期的早期被調用,以確保在執行時間代碼時存在所有必需的JCR結構。
雖然Repo Init指令碼本身作為指令碼在ui.config
項目中生存,但它們可以而且應該用於定義以下可變結構:
回購初始化指令碼會儲存為RepositoryInitializer
OSGi工廠組態的scripts
項目,因此可透過執行模式隱式定位,允許AEM作者與AEM Publish Services的回購初始化指令碼之間,或甚至是環境(開發、階段與產品)之間的差異。
回購初始化OSGi配置以.config
OSGi配置格式寫得最好,因為它們支援多行,這是使用.cfg.json
定義OSGi配置的最佳做法的例外。
請注意,在定義「使用者」和「群組」時,只有群組會視為應用程式的一部分,而且應在此處定義其功能的整數。 「組織使用者」和「群組」仍應在AEM的執行時期中定義;例如,如果自訂工作流程將工作指派給指名的群組,則該群組應透過AEM應用程式中的回購初始化定義,但是,如果群組僅是組織性的,例如「Wendy's Team」和「Sean's Team」,則這些工作是最佳定義,並在AEM的執行時期進行管理。
回購初始化指令碼必須定義在內嵌scripts
欄位中,並且references
配置將無法工作。
Apache Sling Repo Init檔案中提供回購初始指令碼的完整辭彙。
有關完整的代碼片段,請參見下面的回購初始化代碼片段部分。
代碼包要求將FileVault Maven插件的配置配置為引用<repositoryStructurePackage>
,以強制實施結構依賴性的正確性(以確保一個代碼包不會安裝在另一個代碼包上)。 您可以為項目建立自己的儲存庫結構包。
這只是程 式碼套件的必要 ,也就是任何標有的套件 <packageType>application</packageType>
。
要瞭解如何為應用程式建立儲存庫結構包,請參閱開發儲存庫結構包。
請注意,內容包(<packageType>content</packageType>
)不需要此儲存庫結構包。
有關完整的程式碼片段,請參閱下面的POM XML程式碼片段一節。
內容或程式碼套件會放在特殊的「側車」檔案夾中,並可定位為使用FileVault Maven增效模組的<embeddeds>
組態,在AEM作者、AEM發佈或兩者上安裝。 請注意,<subPackages>
組態不應使用。
常見使用案例包括:
若要定位AEM作者、AEM發佈或兩者,套件會內嵌在all
容器套件中的特殊資料夾位置,格式如下:
/apps/<app-name>-packages/(content|application|container)/install(.author|.publish)?
劃分此資料夾結構:
第1級資料夾必須 /apps
。
第2層資料夾代表在資料夾名稱后面已修正-packages
的應用程式。 通常,所有子包都只嵌入一個第2級資料夾,但可以建立任意數量的第2級資料夾以最好地表示應用程式的邏輯結構:
/apps/my-app-packages
/apps/my-other-app-packages
/apps/vendor-packages
根據慣例,子包嵌入資料夾的名稱為尾碼為 -packages
。這可確保部署代碼和內容包 未部署 ,而是不會部署任何子包的目標資料夾, /apps/<app-name>/...
從而導致破壞性和循環安裝行為。
第3級資料夾必須是
application
、 content
或 container
第4層資料夾包含子包,且必須是下列其中一個:
install
若要同時安裝 在 AEM作者和AEM發佈上install.author
僅 安裝 在AEM作者上install.publish
若要 僅安裝在AEM發佈注意事項,僅 install.author
支援 install.publish
和為支援目標。不支援其 他執行模 式。例如,包含AEM作者和發佈特定套件的部署可能如下所示:
all
容器套件內嵌下列套件,以建立單一的部署工件
ui.apps
內嵌於 /apps/my-app-packages/application/install
將程式碼部署至AEM作者和AEM發佈ui.apps.author
內嵌於 /apps/my-app-packages/application/install.author
僅將程式碼部署至AEM作者ui.content
內嵌於 /apps/my-app-packages/content/install
將內容和設定部署至AEM作者和AEM發佈ui.content.publish
內嵌於 /apps/my-app-packages/content/install.publish
僅將內容和設定部署至AEM發佈有關完整的程式碼片段,請參閱下面的POM XML程式碼片段一節。
由於容器封裝中內嵌了程式碼和內容子封裝,所以必須將內嵌的目標路徑新增至容器專案的filter.xml
,以確保內嵌的封裝在建立時會包含在容器封裝中。
只需為包含要部署的子包的任何第2級資料夾添加<filter root="/apps/%3Cmy-app%3E-packages?lang=zh-Hant"/>
條目。
有關完整的程式碼片段,請參閱下面的POM XML程式碼片段一節。
所有套件都必須透過Adobe的公用Maven物件存放庫或可存取的公用、可參考的第三方Maven物件存放庫取得。
如果第三方套件位於 Adobe的公用Maven工件存放庫,則Adobe Cloud manager無需進一步設定即可解析工件。
如果第三方包位於公 用的第三方Maven對象儲存庫,則必須按照上述方法在項目中註冊並嵌入此存 pom.xml
儲庫 。
第三方應用程式/連接器應使用其all
封裝內嵌為專案的容器(all
)封裝。
添加Maven依賴項遵循標準Maven做法,並且嵌入第三方對象(代碼和內容包)的如上所述。
有關完整的程式碼片段,請參閱下面的POM XML程式碼片段一節。
ui.content
包中ui.apps
之間的包依賴性為了確保軟體包的正確安裝,建議建立軟體包間相關性。
一般規則是包含可變內容(ui.content
)的包,該包應依賴於支援可變內容的渲染和使用的不可變代碼(ui.apps
)。
此一般規則的一個明顯例外是,如果不可變代碼包(ui.apps
或任何其他),僅包含OSGi捆綁。 如果是,則AEM套件不應宣告對它的依賴。 這是因為不可變的代碼包僅包含OSGi捆綁包未向AEM Package Manager註冊,因此,任何根據它的AEM包都將具有不滿足的依賴性,並且無法安裝。
有關完整的程式碼片段,請參閱下面的POM XML程式碼片段一節。
內容包依賴項的常見模式有:
簡單案例將ui.content
可變內容包設定為依賴於ui.apps
不可變代碼包。
all
沒有依賴性
ui.apps
沒有依賴性ui.content
depsants on ui.apps
複雜的部署會根據簡單的情況展開,並設定對應可變內容與不可變代碼套件之間的相依性。 根據需要,也可以在不可變代碼包之間建立相依性。
all
沒有依賴性
common.ui.apps.common
沒有依賴性site-a.ui.apps
depsants on common.ui.apps
site-a.ui.content
depsants on site-a.ui.apps
site-b.ui.apps
depsants on common.ui.apps
site-b.ui.content
depsants on site-b.ui.apps
本文中概述的專案結構和組織為完全相容的本機開發AEM例項。
以下是Maven pom.xml
組態程式碼片段,可新增至Maven專案,以符合上述建議。
程式碼和內容封裝 (部署為子封裝) 必須依其包含的內容來宣告 應用程式或內容的封裝類型。
容器all/pom.xml
專案不宣告<packageType>
。
代碼包必須將其packageType
設定為application
。
在ui.apps/pom.xml
中,filevault-package-maven-plugin
外掛程式聲明的<packageType>application</packageType>
組建配置指令會聲明其軟體包類型。
...
<build>
<plugins>
<plugin>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>filevault-package-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<group>${project.groupId}</group>
<name>my-app.ui.apps</name>
<packageType>application</packageType>
<accessControlHandling>merge</accessControlHandling>
<properties>
<cloudManagerTarget>none</cloudManagerTarget>
</properties>
</configuration>
</plugin>
...
內容包必須將其packageType
設定為content
。
在ui.content/pom.xml
中, filevault-package-maven-plugin
外掛程式聲明的<packageType>content</packageType>
組建配置指令會聲明其軟體包類型。
...
<build>
<plugins>
<plugin>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>filevault-package-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<group>${project.groupId}</group>
<name>my-app.ui.content</name>
<packageType>content</packageType>
<accessControlHandling>merge</accessControlHandling>
<properties>
<cloudManagerTarget>none</cloudManagerTarget>
</properties>
</configuration>
</plugin>
...
在每個產生套件的專 案中 ,除容器(all
)專案外,將外掛程式聲明的 <cloudManagerTarget>none</cloudManagerTarget>
組態新增至外掛程式宣告的組態,以確 <properties>
filevault-package-maven-plugin
保Adobe Cloud Manager不會部署它們。容器(all
)套件應是透過Cloud Manager部署的單一套件,而Cloud Manager又嵌入所有必要的程式碼和內容套件。
...
<build>
<plugins>
<plugin>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>filevault-package-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
...
<properties>
<cloudManagerTarget>none</cloudManagerTarget>
</properties>
</configuration>
</plugin>
...
包含回購初始化指令碼的回購初始化指令碼是在RepositoryInitializer
OSGi工廠配置中通過scripts
屬性定義的。 請注意,由於這些指令碼是在OSGi配置中定義的,因此可以使用通常的../config.<runmode>
資料夾語義,按運行模式輕鬆確定其範圍。
請注意,由於指令碼通常是多行宣告,因此在.config
檔案中定義它們比在JSON架構的.cfg.json
格式更容易。
/apps/my-app/config.author/org.apache.sling.jcr.repoinit.RepositoryInitializer-author.config
scripts=["
create service user my-data-reader-service
set ACL on /var/my-data
allow jcr:read for my-data-reader-service
end
create path (sling:Folder) /conf/my-app/settings
"]
scripts
OSGi屬性包含由Apache Sling's Repo Init language定義的指令。
在ui.apps/pom.xml
和聲明代碼包(<packageType>application</packageType>
)的任何其他pom.xml
中,將以下儲存庫結構包配置添加到FileVault Maven插件中。 您可以為項目建立自己的儲存庫結構包。
...
<build>
<plugins>
<plugin>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>filevault-package-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
...
<repositoryStructurePackages>
<repositoryStructurePackage>
<groupId>${project.groupId}</groupId>
<artifactId>ui.apps.structure</artifactId>
<version>${project.version}</version>
</repositoryStructurePackage>
</repositoryStructurePackages>
</configuration>
</plugin>
...
在all/pom.xml
中,將以下<embeddeds>
指令添加到filevault-package-maven-plugin
插件聲明中。 請記住,不使用<subPackages>
組態,因為這將包含/etc/packages
中的子封裝,而非/apps/my-app-packages/<application|content|container>/install(.author|.publish)?
。
...
<plugin>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>filevault-package-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
...
<embeddeds>
<!-- Include the application's ui.apps and ui.content packages -->
<!-- Ensure the artifactIds are correct -->
<!-- OSGi Bundle Jar file that deploys to BOTH AEM Author and AEM Publish -->
<embedded>
<groupId>${project.groupId}</groupId>
<artifactId>my-app.core</artifactId>
<type>jar</type>
<target>/apps/my-app-packages/application/install</target>
</embedded>
<!-- Code package that deploys to BOTH AEM Author and AEM Publish -->
<embedded>
<groupId>${project.groupId}</groupId>
<artifactId>my-app.ui.apps</artifactId>
<type>zip</type>
<target>/apps/my-app-packages/application/install</target>
</embedded>
<!-- OSGi configuration code package that deploys to BOTH AEM Author and AEM Publish -->
<embedded>
<groupId>${project.groupId}</groupId>
<artifactId>my-app.ui.config</artifactId>
<type>zip</type>
<target>/apps/my-app-packages/application/install</target>
</embedded>
<!-- Code package that deploys ONLY to AEM Author -->
<embedded>
<groupId>${project.groupId}</groupId>
<artifactId>my-app.ui.apps.author</artifactId>
<type>zip</type>
<target>/apps/my-app-packages/application/install.author</target>
</embedded>
<!-- Content package that deploys to BOTH AEM Author and AEM Publish -->
<embedded>
<groupId>${project.groupId}</groupId>
<artifactId>my-app.ui.content</artifactId>
<type>zip</type>
<target>/apps/my-app-packages/content/install</target>
</embedded>
<!-- Content package that deploys ONLY to AEM Publish -->
<embedded>
<groupId>${project.groupId}</groupId>
<artifactId>my-app.ui.content.publish-only</artifactId>
<type>zip</type>
<target>/apps/my-app-packages/content/install.publish</target>
</embedded>
<!-- Include any other extra packages -->
<embedded>
<groupId>com.vendor.x</groupId>
<artifactId>vendor.plug-in.all</artifactId>
<type>zip</type>
<target>/apps/vendor-packages/container/install</target>
</embedded>
<embeddeds>
</configuration>
</plugin>
...
在項目 all
的( filter.xml
)中,all/src/main/content/jcr_root/META-INF/vault/definition/filter.xml
包 含要部-packages
署的子包的所有資料夾:
<filter root="/apps/my-app-packages"/>
如果嵌入目標中使用多個/apps/*-packages
,則必須在此處列舉所有<a0/>。
添加更多Maven儲存庫可能會延長Maven構建時間,因為將檢查其他Maven儲存庫是否具有相關性。
在反應堆項目的pom.xml
中,添加任何必要的第三方公共Maven儲存庫指令。 完整<repository>
配置應可從第三方儲存庫提供方獲得。
<repositories>
...
<repository>
<id>3rd-party-repository</id>
<name>Public 3rd Party Repository</name>
<url>https://repo.3rdparty.example.com/...</url>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
...
</repositories>
ui.content
包中ui.apps
之間的包依賴性在ui.content/pom.xml
中,將以下<dependencies>
指令添加到filevault-package-maven-plugin
插件聲明中。
...
<plugin>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>filevault-package-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
...
<dependencies>
<!-- Declare the content package dependency in the ui.content/pom.xml on the ui.apps project -->
<dependency>
<groupId${project.groupId}</groupId>
<artifactId>my-app.ui.apps</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
...
</configuration>
</plugin>
...
在all/pom.xml
中添加maven-clean-plugin
插件,該插件將在Maven構建之前清除目標目錄。
<plugins>
...
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<executions>
<execution>
<id>auto-clean</id>
<!-- Run at the beginning of the build rather than the default, which is after the build is done -->
<phase>initialize</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>