使用 SpringSource Slices 構建模組化 Web 應用

工程 | Rob Harrop | 2009 年 6 月 22 日 | ...

更新:增加了 Git 子模組說明。

我過去曾談到為真正的模組化應用提供支援,現在很高興宣佈您可以訪問 SpringSource Slices 的早期原型程式碼了。

構建與安裝

您可以從我們的 Git 倉庫訪問原始碼

git clone git://git.springsource.org/slices/slices.git
git submodule init
git submodule update

要構建 Slices 的打包版本,只需在 build-slices 目錄中執行 ant clean jar package

cd slices/build-slices
ant clean jar package

這將在 target/artifacts 中生成一個 zip 檔案,其中包含 Slices 子系統,然後可以將其安裝到 dm Server 2.0 上

安裝 Slices 只需要將新子系統新增到 dm Server,然後更新 dm Server 的配置檔案以啟動新子系統即可。Slices 應該相容任何近期的 dm Server 2.0 快照版本。我這裡使用的是 2.0.0.CI-R326-B274,我已經下載並解壓到我的桌面上了

 unzip target/artifacts/springsource-slices-BUILD-20090622083953.zip -d ~/Desktop/springsource-dm-server-2.0.0.CI-R326-B274

接下來,必須更新 dm Server 的 kernel.properties 配置,以包含新的 slices 子系統。開啟你的 dm Server 安裝目錄下的 config/kernel.properties 檔案,編輯 Profile Configuration 部分,列出 slices 子系統並給配置檔案一個合適的名稱(我稱之為 slices)

#######################
# Profile Configuration
#######################
profile.name=slices
profile.subsystems=	com.springsource.server.web,com.springsource.osgi.slices
profile.optionalSubsystems=

儲存更新的檔案,然後就可以嘗試 Slices 示例應用了。

試用示例應用

Slices 倉庫包含一個 Spring 3 PetClinic 示例的版本,隨著我們為 Slices 新增新功能,我們不斷對其進行增強和改進。

在使用示例之前,必須將其依賴項新增到你的 dm Server 安裝目錄中。依賴項列在示例的 dependencies.txt 檔案中。將每個列出的依賴項下載到安裝目錄的 repository/bundles/usr 目錄。然後,使用 -clean 啟動選項啟動 dm Server

./bin/startup.sh -clean

現在是構建和部署示例的時候了。進入 slices/samples/slices-petclinic/com.springsource.slices.petclinic.host 目錄並執行 ant clean jar

cd samples/slices-petclinic/com.springsource.slices.petclinic.host
ant clean jar

然後可以透過將生成的 war 包複製到 dm Server 的 pickup 目錄來部署 host

 cp target/artifacts/com.springsource.slices.petclinic.host.war ~/Desktop/springsource-dm-server-2.0.0.CI-R326-B274/pickup/

現在可以透過 https://:8080/petclinic 訪問 host 了

petclinic-no-slices

接下來,進入 slices/samples/slices-petclinic/com.springsource.slices.petclinic.appointments 目錄並執行 ant clean jar 來構建 appointments slice

cd samples/slices-petclinic/com.springsource.slices.petclinic.appointments
ant clean jar

現在可以透過將生成的 war 包複製到 dm Server 的 pickup 目錄來部署 slice 了

cp target/artifacts/com.springsource.slices.petclinic.appointments.war  ~/Desktop/springsource-dm-server-2.0.0.CI-R326-B274/pickup/

重新整理 https://:8080/petclinic,它現在將反映 appointments slice 的存在,並帶有新的 Appointments 連結

petclinic-appointments-slice

如果您願意,現在可以從 pickup 目錄中刪除 appointments war 包,以再次看到 slice 消失。

Slices 應用的結構

使用 Slices,您可以從多個 OSGi bundle 構建一個 Web 應用,每個 bundle 為您的應用 URL 空間中的一個獨立子部分提供內容。Slices 應用採用父子結構排列,每個應用最多有一個父級,稱為 host,以及零個或多個子級,稱為 slices。我們正在開發一個簡單的 Slices 示例,它看起來像這樣

slice-anatomy

Host 內部

petclinic.host bundle 包含所有共享內容,如圖片和 CSS,以及用於顯示首頁的控制器和 JSPs。host bundle 只是一個符合 RFC66 標準的 web bundle,其 web.xml 中配置了 SliceHostFilter。下面的程式碼片段展示了 petclinic.host bundle 中的 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	
    <filter>
    	<filter-name>host-filter</filter-name>
    	<filter-class>com.springsource.osgi.slices.core.SliceHostFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>host-filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

	<!-- Enables clean URLs with JSP views e.g. /welcome instead of /app/welcome -->
	<filter>
		<filter-name>UrlRewriteFilter</filter-name>
		<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>UrlRewriteFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
		
	<!-- Handles all requests into the application -->
	<servlet>
		<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>
				/WEB-INF/spring/*.xml
			</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<!-- Maps all /app requests to the DispatcherServlet for handling -->
	<servlet-mapping>
		<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
		<url-pattern>/app/*</url-pattern>
	</servlet-mapping>

  	<!-- Serves static resource content from the webapp root & .jar files such as spring-js.jar -->
	<servlet>
		<servlet-name>Resources Servlet</servlet-name>
		<servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
		<load-on-startup>0</load-on-startup>
	</servlet>
		
	<!-- Map all /resources requests to the Resource Servlet for handling -->
	<servlet-mapping>
		<servlet-name>Resources Servlet</servlet-name>
		<url-pattern>/resources/*</url-pattern>
	</servlet-mapping>	
	
</web-app>

如您所見,host 可以有任何正常的 servlet 和 filter 對映,但它需要 SliceHostFilter 才能將請求路由到其 slices。

Slice 內部

Slice 是一個 bundle,其外觀和功能類似於標準的 RFC66 web bundle,但它沒有自己的 ServletContext。相反,slice 執行在其 host 的 ServletContext 下。

Slices 的主要設計目標之一是確保 slice 開發與標準 web 應用開發儘可能相似。為此,您建立 slice web 內容的方式與為任何應用建立 web 內容的方式完全相同,即使用 web.xml。這是 petclinic.appointments bundle 中的 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- Handles all requests into the application -->
	<servlet>
		<servlet-name>appointments</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>		
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<!-- Maps all /app requests to the DispatcherServlet for handling -->
	<servlet-mapping>
		<servlet-name>appointments</servlet-name>
		<url-pattern>/app/*</url-pattern>
	</servlet-mapping>
	
</web-app>

appointments slice 只是委託給了 Spring DispatcherServlet。可以在 slice 中正常使用 Spring MVC。

slice 可以透過引用自身不存在的資源名稱來訪問 host bundle 中的資源。如果 slice 想要訪問 host 中的資源,即使它自身也有同名資源,也可以使用 host: 字首來實現

ServletContext context =  getServletContext();
context.getResource("host:/WEB-INF/some.config.xml");

slice 需要定義它想要附加到哪個 host,這透過 Slice-Host manifest header 實現。 Slice-ContextPath header 定義了 slice 處理的 URL 部分

Bundle-SymbolicName: petclininc.appointments
Slice-Host: petclinic.host;version="[1.0, 2.0)"
Slice-ContextPath: /appointments

Slice 生命週期

host 可以在沒有附加任何相應的 slice 的情況下執行。當一個 slice 安裝到與某個 host 匹配的伺服器中時,該 slice 將附加到該 host。此時,host URL 部分中與新附加的 slice 的 Slice-ContextPath 匹配的子部分將被路由到該 slice。

當 slice 被解除安裝時,曾經路由到該 slice 的 URL 空間部分現在直接路由回 host。透過這種方式,您可以在 host 中建立內容來處理丟失的 slices。

今天 Slice 可以做些什麼?

截至撰寫本文時,Slices 程式碼庫在 Slice 中支援以下功能

  • Servlets 和 servlet 對映
  • JSPs
  • Spring MVC
  • Slice 區域性會話
  • 自動回退到應用範圍會話
  • 透過 ServletContext 進行 Slice 區域性資源查詢
  • 自動回退到 host 中的資源查詢
  • 使用 host: 進行顯式 host 資源查詢

接下來是什麼?

我們正在為 Slices 開發許多有趣的新功能,包括

  • slices 中的 Filters 和 filter 對映
  • slices 中的 Listeners
  • UI 組合框架。您可以在 Petclinic 示例中看到手動實現方法
  • Tiles 2 整合
  • 完整的示例應用
  • SpringSource Tool Suite 支援

如果您有任何功能建議或發現錯誤,請隨時在我們的 JIRA 上提交問題。

如果您想密切關注進展,可以關注我們的 Git 倉庫和 #dmserver Twitter 標籤。

訂閱 Spring 電子報

訂閱 Spring 電子報,保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您快速提升。

瞭解更多

獲取支援

Tanzu Spring 透過一個簡單的訂閱提供對 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視全部