【转】 使用 AppFuse 快速构建 J2EE 应用
|
級(jí)別: 中級(jí)
沈 銳 (shenrui@cn.ibm.com), 軟件工程師, IBM CSDL
2006 年 10 月 19 日
本 文以一個(gè) J2EE 開(kāi)發(fā)者的角度,借助一個(gè)簡(jiǎn)單的應(yīng)用示例,在融合了個(gè)人經(jīng)驗(yàn)的基礎(chǔ)上介紹了如何用 AppFuse 一步步地構(gòu)建 J2EE 項(xiàng)目。通過(guò)閱讀本文,讀者不僅能夠?qū)W會(huì)用 AppFuse 進(jìn)行開(kāi)發(fā),而且能夠充分體會(huì)到 AppFuse 提供的“快速開(kāi)發(fā)”的優(yōu)越性。關(guān)于 AppFuse 的特性、架構(gòu)以及為什么要使用 AppFuse,AppFuse 的創(chuàng)始人 Matt Raible 在 《使用 AppFuse 的七個(gè)理由》一文中已經(jīng)做了很詳盡的闡述,這里就不再贅言。本文將著力于實(shí)踐,即如何運(yùn)用 AppFuse 開(kāi)發(fā) J2EE 應(yīng)用。
使 用 AppFuse,你需要對(duì) Ant 有一些基本的了解,比如什么叫 target、什么是 build.xml 以及如何運(yùn)行 Ant,等等。如果你現(xiàn)在還不知道 Ant 是什么,就需要找些相關(guān)資料學(xué)習(xí)一下。下表列出了本文中用到的也是較為常用的 AppFuse 的 target:
表 1. Ant 中常用的 AppFuse target
| new | 這個(gè) target 是使用 AppFuse 必須要用到的,它用來(lái)在 AppFuse 同級(jí)的目錄下創(chuàng)建一個(gè)新項(xiàng)目。創(chuàng)建過(guò)程是交互式的,會(huì)讓用戶輸入項(xiàng)目名稱、數(shù)據(jù)庫(kù)名稱以及根包路徑。 | AppFuse 安裝目錄下的 build.xml |
| setup | 用于初始化一個(gè)新的項(xiàng)目,它包含了從數(shù)據(jù)庫(kù)創(chuàng)建、Tomcat 設(shè)置到 war 文件的生成和部署等一系列操作。 | 項(xiàng)目根目錄下的 build.xml |
| deploy | 如果你修改的代碼不涉及到數(shù)據(jù)庫(kù)的更改,那么可以使用這個(gè) target,因?yàn)樗回?fù)責(zé)生成并重新部署 war 包。 | 項(xiàng)目根目錄下的 build.xml |
| setup-db | 如果你只是要對(duì)數(shù)據(jù)庫(kù)進(jìn)行更改,使用這個(gè) target。比如,重新創(chuàng)建數(shù)據(jù)庫(kù),重新加載樣本數(shù)據(jù)等操作。 | 項(xiàng)目根目錄下的 build.xml |
| install | AppGen 的 target。如果你不希望使用 AppGen 幫你生成 dao 類和 service 類以及其他的代碼,就使用這個(gè) target。 | extras/appgen 目錄下的 build.xml |
| install-detailed | AppGen 的 target。如果你希望使用 AppGen 幫你生成所有代碼,就使用這個(gè) target。 | extras/appgen 目錄下的 build.xml |
本文將按如下順序展開(kāi)敘述:
- 示例介紹
- 搭建開(kāi)發(fā)環(huán)境
- 新建項(xiàng)目
- 創(chuàng)建數(shù)據(jù)庫(kù)表
- 用 AppGen 生成代碼
- 根據(jù)項(xiàng)目需求調(diào)整代碼
- 其他功能
- 語(yǔ)言國(guó)際化
- 頁(yè)面布局和樣式
- 系統(tǒng)安全
- 事務(wù)控制
- 日志
- 郵件
- 緩存
|
示例介紹
本 文的示例實(shí)現(xiàn)對(duì)員工信息的增刪查改等基本功能。用 Tapestry 實(shí)現(xiàn)表示層,用 Hibernate 開(kāi)發(fā)持久層,用 Spring 提供事務(wù)控制等跨模塊服務(wù),并用 Acegi 進(jìn)行安全管理。本示例只用到一個(gè)域模型:Employee,下面是它的 UML 圖。
圖 1. Employee UML 圖
|
搭建開(kāi)發(fā)環(huán)境
本文的代碼開(kāi)發(fā)平臺(tái)采用的是 Windows 操作系統(tǒng),因此,以下環(huán)境設(shè)置也是針對(duì) Windows 操作系統(tǒng)的。
- 從 AppFuse 下載頁(yè)面 下載 appfuse-tapestry-1.9.3-src.zip,并解壓縮在任意目錄下。這個(gè) zip 已經(jīng)定制了使用 Tapestry 作為表現(xiàn)層的實(shí)現(xiàn)框架,因而使用起來(lái)較為直接。
- 從 http://java.sun.com 下載最新的 JDK,并安裝或解壓縮到任意目錄下。本文采用 JDK 1.5.0。設(shè)置環(huán)境變量 JAVA_HOME 指向 JDK 所在的目錄,并在 PATH 中添加 %JAVA_HOME%/bin。
- 從 http://jakarta.apache.org/tomcat 下載最新版的 Tomcat,并安裝或解壓縮到任意目錄下。本文采用 Tomcat 5.5.17。設(shè)置環(huán)境變量 CATALINA_HOME 指向 Tomcat 的安裝目錄。
- 從 http://ant.apache.org下 載最新版的 Ant,并解壓縮到任意目錄下。AppFuse 要求的最低版本是 1.6.2,本文采用的是 1.6.5。設(shè)置 ANT_HOME 指向 Ant 所在的目錄,并在 PATH 中添加 %ANT_HOME%/bin。另外,要拷貝一個(gè) junit.jar 到 %ANT_HOME%/lib 下,如果 lib 下沒(méi)有 junit.jar,AppFuse 的腳本在運(yùn)行時(shí)會(huì)給出警告信息。junit.jar 可以從 http://www.junit.org 獲得,也可以從 %AppFuse%/lib/junit3.8.1 目錄下獲得。
- 從 http://www.mysql.com 下載最新版的 MySQL,并安裝或解壓縮到任意目錄下。本文采用的是 5.0。
- 從 http://www.eclipse.org 下載 Eclipse 3.1 或 3.2,安裝到任意目錄下。
AppFuse 的 Ant 腳本可以在命令行中運(yùn)行,也可以在 Eclipse 里運(yùn)行。有關(guān)如何在 Eclipse 里執(zhí)行 Ant 腳本,請(qǐng)參考《用Eclipse開(kāi)發(fā)AppFuse應(yīng)用》。到此,我們已經(jīng)為 AppFuse 開(kāi)發(fā)應(yīng)用準(zhǔn)備好了環(huán)境,下面讓我們開(kāi)始使用 AppFuse 創(chuàng)建項(xiàng)目。
|
新建項(xiàng)目
AppFuse 的便捷與強(qiáng)大之處在于它已經(jīng)為我們提供了多種開(kāi)源框架的集成,并且通過(guò)使用 Ant 將所有的構(gòu)建過(guò)程自動(dòng)化。另外,AppFuse 利用 XDoclet 能夠?yàn)槲覀兩山^大多數(shù)重要的代碼,例如 dao 類、service 類以及測(cè)試用例,等等,并且能夠?qū)⒋罅康呐渲梦募惨徊⑸珊?#xff0c;從而極大地節(jié)省了開(kāi)發(fā)人員的時(shí)間。
用 AppFuse 進(jìn)行開(kāi)發(fā)通常有三種模式:“自上而下”,“自下而上”以及“混合模式”。采用“自上而下”(由 Java 對(duì)象向數(shù)據(jù)庫(kù)對(duì)象創(chuàng)建的過(guò)程)的方式固然比較符合“面向?qū)ο蟆钡脑O(shè)計(jì)思維,但是為此要編寫大量的 XDoclet 的 tag 也確是一件痛苦的事情。相比較而言,采用“自下而上”(由數(shù)據(jù)庫(kù)對(duì)象生成 Java 對(duì)象的過(guò)程)就顯得簡(jiǎn)單許多 -- 只需要提供數(shù)據(jù)庫(kù)表結(jié)構(gòu)。然而,對(duì)于較為復(fù)雜的系統(tǒng),尤其是類之間具有大量的關(guān)聯(lián)的情形,仍然需要采用“自上而下”的創(chuàng)建模式。因此,在實(shí)際的項(xiàng)目開(kāi)發(fā) 中,將兩種模式進(jìn)行混合使用比較常見(jiàn),這也就是“混合”模式。本文采用“自下而上”的模式。
本文的 AppFuse 安裝在 "c:\opt" 下面。打開(kāi)命令行控制臺(tái),進(jìn)入 "c:\opt\appfuse",運(yùn)行 “ant new”,為簡(jiǎn)單起見(jiàn),所有參數(shù)選用默認(rèn)值,見(jiàn)圖 2。
圖 2. ant new -- 新建項(xiàng)目
腳本運(yùn)行成功后,新項(xiàng)目創(chuàng)建在 c:\opt\myapp 下(與 AppFuse 目錄同級(jí)),myapp 是 AppFuse 默認(rèn)的項(xiàng)目名稱。將該項(xiàng)目導(dǎo)入到 Eclipse 中,并根據(jù) 《用Eclipse開(kāi)發(fā)AppFuse應(yīng)用》 進(jìn)行必要的設(shè)置。以下是兩個(gè)你可能需要進(jìn)行的配置:
- AppFuse 默認(rèn)連接 MySQL 的用戶名是 root,密碼為空。如果你的 root 密碼不是空,需要修改 C:\opt\myapp\build.properties 中的 database.admin.password 項(xiàng),記得將注釋去掉。
- AppFuse 默認(rèn)不是用 utf-8 創(chuàng)建數(shù)據(jù)庫(kù),如果你需要支持多語(yǔ)言,需要修改 C:\opt\myapp\metadata\sql\mysql-create.sql 中的創(chuàng)建數(shù)據(jù)庫(kù)的語(yǔ)句,修改如下:
清單 1. 創(chuàng)建數(shù)據(jù)庫(kù)語(yǔ)句create database if not exists @DB-NAME@ CHARACTER SET utf8 COLLATE utf8_general_ci;
|--10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error: The previous line is longer than the max of 90 characters ---------|
注:AppFuse 會(huì)在構(gòu)建期將 @DB-NAME@ 替換成你指定的數(shù)據(jù)庫(kù)名(本文中為“mydb”)。
在 c:\opt\myapp 下運(yùn)行“ant setup test-all”。“setup” 完成了很多“設(shè)置”工作:創(chuàng)建數(shù)據(jù)庫(kù)、構(gòu)建 dao 和 serive 類、加載樣本數(shù)據(jù)、創(chuàng)建 war 文件并部署到 tomcat,等等。“test-all” 運(yùn)行所有的測(cè)試用例:對(duì) dao,service 以及頁(yè)面的測(cè)試。如果這個(gè)腳本運(yùn)行成功,說(shuō)明開(kāi)發(fā)環(huán)境一切就緒。這時(shí),啟動(dòng) Tomcat,通過(guò)訪問(wèn) http://localhost:8080/myapp 就能夠看到 AppFuse 的登錄界面了。AppFuse 預(yù)定義了兩個(gè)用戶:mraible 和 tomcat,密碼都是 tomcat。mraible 屬于管理員角色(能夠管理用戶信息),tomcat 屬于普通用戶角色。用 mraible 登錄可以看到 圖 3的界面。
圖 3. AppFuse 的初始界面
或許此時(shí),你已驚奇地發(fā)現(xiàn),自己不過(guò)只運(yùn)行了一次 Ant 腳本,但是系統(tǒng)已經(jīng)擁有“用戶管理”、“郵件”、“文件上傳” 等功能 -- 這就是 AppFuse “開(kāi)箱即用”的優(yōu)勢(shì)。接下來(lái)讓我們開(kāi)始開(kāi)發(fā)前述的應(yīng)用示例。
|
創(chuàng)建數(shù)據(jù)庫(kù)表
在 mydb 數(shù)據(jù)庫(kù)中執(zhí)行如下語(yǔ)句創(chuàng)建 employee 表:
清單 2. 創(chuàng)建 employee 語(yǔ)句
| CREATE TABLE `employee` ( `id` bigint(20) NOT NULL auto_increment, `code` varchar(10) NOT NULL, `dept` varchar(50) NOT NULL, `name` varchar(20) NOT NULL, `status` varchar(10) NOT NULL, `telephone` varchar(20) default NULL, `title` varchar(50) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
|
用 AppGen 生成代碼
AppFuse 自帶了一個(gè)代碼生成工具 -- AppGen,它位于 c:\opt\myapp\extras\appgen 目錄下面。AppGen 可以生成絕大部分我們需要的代碼,比如 dao 類,service 類,菜單、增刪改的 web 頁(yè)面、配置文件、樣本數(shù)據(jù),等等。AppGen 利用 XDoclet 生成代碼,因此可以在 extras/appgen/src 看到很多 .xdt 文件,這些就是 XDoclet 的模版定義文件。如果你希望自己編寫 dao 和 service 類,就運(yùn)行“install”這個(gè) target,否則就用 “install-detailed” ,它可以幫你搞定一切。下面就讓我們來(lái)運(yùn)行 “install-detailed” 生成代碼。在 c:\opt\myapp\extras\appgen 下運(yùn)行 “ant install-detailed”。
清單 3. 運(yùn)行 install-detailed
| ... [input] Would you like to generate code from a table or POJO? (table,pojo) table [input] What is the name of your table (i.e. person)? employee [input] What is the name, if any, of the module for your table (i.e. organization)? hr ... |
前兩個(gè)問(wèn)題都很直觀:選擇從 table 生成代碼,表名是 employee。第三個(gè)問(wèn)題是讓用戶輸入使用的模塊名,如果你希望 AppFuse 幫你按模塊生成代碼的話,就需要輸入一個(gè)模塊名稱。這里,我們輸入“hr”。如果運(yùn)行成功,在 Eclipse 中會(huì)看到如下的目錄結(jié)構(gòu):
圖 4. “install-detailed” 執(zhí)行后的 Eclipse
表 2 列出了 "install-detailed" 生成的主要文件。
表 2. "install-detailed" 生成的主要文件列表
| myapp/src/dao/org/appfuse/dao/hibernate/applicationContext-hibernate.xml | 在其中增加了 employeeDao 的聲明 |
| myapp/src/dao/org/appfuse/hr/model/Employee.java | Employee 類 -- Java Bean |
| myapp/build/dao/gen/org/appfuse/hr/model/Employee.hbm.xml | Employee 類的 Hibernate 映射文件 |
| myapp/src/dao/org/appfuse/hr/dao/EmployeeDao.java | 定義關(guān)于 employee 的 dao 層的操作 |
| myapp/src/dao/org/appfuse/hr/dao/hibernate/EmployeeDaoHibernate.java | EmployeeDao 的 Hibernate 實(shí)現(xiàn)類 |
| myapp/src/service/org/appfuse/service/applicationContext-service.xml | 在其中增加了employeeManager的聲明 |
| myapp/src/service/org/appfuse/hr/service/EmployeeManager.java | 定義關(guān)于 employee 的 service 層的操作 |
| myapp/src/service/org/appfuse/hr/service/impl/EmployeeManagerImpl.java | EmployeeManager 的實(shí)現(xiàn)類 |
| myapp/src/web/org/appfuse/hr/webapp/action/EmployeeForm.java | employee 的添加/修改頁(yè)面對(duì)應(yīng)的 tapestry 類 |
| myapp/src/web/org/appfuse/hr/webapp/action/EmployeeList.java | employee 的列表頁(yè)面對(duì)應(yīng)的 tapestry 類 |
| myapp/test/dao/org/appfuse/hr/dao/EmployeeDaoTest.java | employee dao 類的測(cè)試用例 |
| myapp/test/service/org/appfuse/hr/dao/EmployeeManagerTest.java | employee service 類的測(cè)試用例 |
| myapp/test/web/org/appfuse/hr/webapp/action/EmployeeFormTest.java | employee 添加/修改頁(yè)面類的測(cè)試用例 |
| myapp/test/web/org/appfuse/hr/webapp/action/EmployeeFormTest.java | employee 列表頁(yè)面類的測(cè)試用例 |
| myapp/web/pages/hr/employeeForm.html | employee 添加/修改頁(yè)面 html 模版文件 |
| myapp/web/pages/hr/employees.html | employee 列表頁(yè)面 html 模版文件 |
| myapp/web/pages/hr/employeeForm.page | employee 添加/修改頁(yè)面規(guī)格文件 |
| myapp/web/pages/hr/employees.page | employee 列表頁(yè)面規(guī)格文件 |
不 過(guò),AppFuse 并不知道開(kāi)發(fā)者需要加載哪些 hbm 文件,所以要手工將 Employee.hbm.xml 文件添加到配置文件中:打開(kāi) applicationContext-hibernate.xml,在 “sessionFactory” 的 bean 聲明中,找到 “mappingResources” 屬性的定義,增加 “<value>org/appfuse/hr/model/Employee.hbm.xml</value>”。
清單 4. applicationContext-hibnerate.xml 中添加 Employee.hbm.xml
| ... <beans> <!-- Hibernate SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| <property name="dataSource" ref="dataSource"/> <property name="mappingResources"> <list> <value>org/appfuse/hr/model/Employee.hbm.xml</value> <value>org/appfuse/model/Role.hbm.xml</value> <value>org/appfuse/model/User.hbm.xml</value> </list> </property> ... |
在 c:\opt\myapp 下運(yùn)行 “ant deploy”。打開(kāi) “http://localhost:8080/myapp”,用 mraible/tomcat 登錄,“Employee List” 已經(jīng)被添加到菜單里了。
圖 5. myapp 的原始主頁(yè)面
點(diǎn)擊 “Employee List” 鏈接,進(jìn)入“員工信息列表”頁(yè)面。
圖 6. myapp 的原始員工信息列表頁(yè)面
點(diǎn)擊“添加”按鈕或點(diǎn)擊任意一行數(shù)據(jù),進(jìn)入“員工信息添加/修改/刪除”頁(yè)面。
圖 7. myapp 的原始員工信息添加/修改/刪除頁(yè)面
不難看出,雖然 AppFuse 幫我們生成了頁(yè)面,但是這些頁(yè)面并非那么“理想”,我們?nèi)匀恍枰鶕?jù)實(shí)際的需求做些調(diào)整。
|
根據(jù)項(xiàng)目需求調(diào)整代碼
在本文中,做了如下代碼修改:
- 將 所有頁(yè)面文字翻譯成中文:AppFuse 中用到的所有 Resource Bundle 文件位于 myapp/web/WEB-INF/classes 目錄下(以ApplicationResources開(kāi)頭的properties文件)。更改 ApplicationResources_zh_CN.properties 的文件編碼方式為“UTF-8”。然后,把 ApplicationResources.properties 中 “# -- Employee-START” 和 “# -- Employee-END” 之間的項(xiàng)拷貝到 ApplicationResources_zh_CN.properties 中,并逐項(xiàng)翻譯成中文。AppFuse 會(huì)在腳本運(yùn)行的時(shí)候自動(dòng)用 native2ascii 進(jìn)行編碼轉(zhuǎn)換。另外,AppFuse 默認(rèn)對(duì) “button.done” 的翻譯是“做”,這不太合適,所以改為“完成”。
- 在“員工信息列表頁(yè)面”去掉了 id 列,并調(diào)整了列的順序:只要修改 employees.html 就可以。
- 在 “員工信息添加/修改/刪除頁(yè)面”,將“所在部門”、“職位”、“狀態(tài)”改為下拉列表:需要修改 employeeForm.html、employeeForm.page、EmployeeForm.java。用 PropertySelection 組件實(shí)現(xiàn)下拉列表,用 Resource Bundle 文件定義真正顯示的選項(xiàng)文本。
- 增加了一個(gè)“人事管理”的角色,用來(lái)執(zhí)行員工信息管理的權(quán)限控制:具體介紹見(jiàn)“系統(tǒng)安全”。
- 添加了一個(gè)新的主題 “mytheme”(只是更改了界面的顏色):具體介紹見(jiàn)“頁(yè)面布局和樣式”。
應(yīng)用了上述修改后,在 c:\opt\myapp 中運(yùn)行 “ant deploy” 重新打包整個(gè)項(xiàng)目并發(fā)布。以下是修改后的界面截圖:
圖 8. 修改后的 myapp 主頁(yè)面
圖 9. 修改后的 myapp 員工信息列表頁(yè)面
圖 10. 修改后的 myapp 員工信息添加/修改/刪除頁(yè)面
圖 11. 修改后的 myapp 用戶管理頁(yè)面
|
其他功能
一個(gè)系統(tǒng)除了包含核心邏輯之外,還有其他一些輔助功能,它們也是非常重要的。下面,讓我們來(lái)看看如何在 AppFuse 中開(kāi)發(fā)這些功能。
語(yǔ)言國(guó)際化
如 果你的系統(tǒng)不僅僅支持一種語(yǔ)言,那么就需要考慮這個(gè)問(wèn)題。在 AppFuse 中,Resource Bundle 文件是位于 web\WEB-INF\classes 目錄下的以 ApplicationResources 開(kāi)頭的 properties 文件。Tapestry 有自己的國(guó)際化文本機(jī)制。但是在 AppFuse 中,并不全是 Tapestry 頁(yè)面,仍有些地方使用 jsp,而這些頁(yè)面使用 JSTL 的 fmt 標(biāo)簽顯示國(guó)際化文本。不過(guò),AppFuse 已經(jīng)將這二者的“源頭”進(jìn)行了整合,因此,對(duì)用戶而言,只需要在 ApplicationResources*.properties 中定義需要國(guó)際化的文本。
但是,在 Eclipse 中可以看到,AppFuse 的 properties 文件默認(rèn)的編碼不是 UTF-8,而是 ISO-8859-1,這樣會(huì)導(dǎo)致最后通過(guò) native2ascii 轉(zhuǎn)換后的文件都是 “???”,所以用戶需要自己把這些文件轉(zhuǎn)成 UTF-8。轉(zhuǎn)換的方法很簡(jiǎn)單:在 properties 文件上點(diǎn)右鍵,在右鍵菜單上選擇 Properties,打開(kāi)屬性窗口后,更改 “Text file encoding” 為 UTF-8。在修改編碼前,最好先把已有的文字拷貝出來(lái),轉(zhuǎn)換好之后再粘貼回去,否則會(huì)導(dǎo)致原先翻譯好的文字變成亂碼。
圖 12. ApplicationResources_zh_CN.properties 的屬性窗口
AppFuse 在發(fā)布項(xiàng)目的時(shí)候,會(huì)自動(dòng)用 native2ascii 轉(zhuǎn)換這些資源文件。如果你想使用其他資源文件名,可以修改 web\WEB-INF\web.xml 中的 “javax.servlet.jsp.jstl.fmt.localizationContext” 的參數(shù)值。
頁(yè)面布局和樣式
使 用 AppFuse,能夠很方便的修改系統(tǒng)的整體布局和樣式,因?yàn)?AppFuse 使用了一種強(qiáng)大的 “CSS框架”。項(xiàng)目創(chuàng)建好之后,在 web\styles 目錄下,有三個(gè)目錄:andreas01,puzzlewithstyle 和 simplicity。這些是 AppFuse 自帶的三種主題,目錄名即 CSS 框架的主題名。屬于“管理員”角色的用戶可以在登錄后通過(guò)在 url 后面添加形如 "?theme=andreas01" 的參數(shù)更改系統(tǒng)使用的主題。如下圖:
圖 13. 應(yīng)用了 “puzzlewithstyle” 的 myapp
系 統(tǒng)默認(rèn)使用的主題由 web\WEB-INF\web.xml 中的 “theme” 參數(shù)指定,AppFuse 默認(rèn)使用的主題是 “simplicity”。更改或創(chuàng)建新的主題也很簡(jiǎn)單,只要在 web\styles 目錄下,新建一個(gè)自己的目錄,并參照已有主題的編寫規(guī)范定義自己的主題。本文中,拷貝了 simplicity 目錄,更名為 “mytheme”,然后將里面的字體顏色從“藍(lán)色”基調(diào)改成了“綠色”基調(diào),并修改 web.xml 中的 theme 參數(shù)值為 “mytheme”,這樣 myapp 默認(rèn)使用的就是 mytheme 的主題了,如圖 8所示。你也可以從 http://css.appfuse.org/themes/ 得到更多關(guān)于 “CSS框架” 的信息。
系統(tǒng)安全
AppFuse 使用 Acegi 進(jìn)行安全管理。Acegi 的配置信息位于 web\WEB-INF\classes\security.xml。事實(shí)上,Acegi 是被集成到 Spring 當(dāng)中的,因此這個(gè)文件是 Spring 的配置文件格式。在 web\WEB-INF\web.xml 中,該文件被指定在應(yīng)用啟動(dòng)前會(huì)被加載:
清單 5. web.xml 關(guān)于 Spring 配置文件的定義
| ... <!-- Context Configuration locations for Spring XML files --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext-*.xml,/WEB-INF/security.xml</param-value> </context-param> ... |
本文關(guān)于系統(tǒng)安全的實(shí)現(xiàn)如下:
清單 6. sample-data.xml 中角色 “hr” 的記錄
| ... <table name='role'> <column>id</column> <column>name</column> <column>description</column> <row> <value>1</value> <value>admin</value> <value><![CDATA[Administrator role (can edit Users)]]></value> </row> <row> <value>2</value> <value>user</value> <value><![CDATA[Default role for all Users]]></value> </row> <row> <value>3</value> <value>hr</value> <value><![CDATA[Role for employee mangement]]></value> </row> </table> ... |
AppFuse 使用 dbunit 加載樣本數(shù)據(jù)到數(shù)據(jù)庫(kù)中,sample-data.xml 為 dbunit 提供樣本數(shù)據(jù)定義。修改完 sample-data.xml,在 c:\opt\myapp\ 下運(yùn)行 “ant db-load”,樣本數(shù)據(jù)被重新加載。這樣,我們就在數(shù)據(jù)庫(kù)中定義了一個(gè)新的角色記錄 “hr”。
| // initialize drop-downs if (getAvailableRoles() == null) { List roles = (List) getServletContext().getAttribute(Constants.AVAILABLE_ROLES); setAvailableRoles(new RoleModel(roles)); } |
將其做如下修改:
| // initialize drop-downs if (getAvailableRoles() == null) { List roles = (List) getServletContext().getAttribute(Constants.AVAILABLE_ROLES); for(int i=0;i<roles.size();i++){ LabelValue role=(LabelValue) roles.get(i); role.setLabel(getText("rolelabel_"+role.getValue())); } setAvailableRoles(new RoleModel(roles)); } |
并在 web\WEB-INF\classes\ApplicationResources_zh_CN.properties 中增加角色名稱的定義:
| rolelabel_admin=系統(tǒng)管理員 rolelabel_user=普通用戶 rolelabel_hr=人事管理 |
AppFuse 默認(rèn)在用戶管理界面上顯示的角色的名稱是表 role 中的名稱,這樣無(wú)論切換到何種語(yǔ)言,角色名稱都是 “admin”、"user"、“hr” 等等,角色名稱不能根據(jù) Locale 用相應(yīng)的語(yǔ)言顯示。因此,本文將角色的名稱用 Resource Bundle 文件定義,數(shù)據(jù)庫(kù)中存儲(chǔ) “key” 值。修改后的效果見(jiàn) 圖 10。
| <bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"> <property name="authenticationManager" ref="authenticationManager"/> <property name="accessDecisionManager" ref="accessDecisionManager"/> <property name="objectDefinitionSource"> <value> PATTERN_TYPE_APACHE_ANT /clickstreams.jsp*=admin /flushCache.*=admin /passwordHint.html*=ROLE_ANONYMOUS,admin,user /reload.*=admin /signup.html*=ROLE_ANONYMOUS,admin,user /users.html*=admin /employees.html*=hr /**/*.html*=admin,user </value> </property> </bean> |
“/employees.html*=hr” 的意思是:只有 hr 這個(gè)角色可以訪問(wèn)形如 “/employees.html*” 的 url。
| <!--Employee-START--> <Menu name="EmployeeMenu" title="employeeList.title" page="/employees.html" roles="hr"/> |--10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| <!--Employee-END--> |
于是,“員工信息維護(hù)”的菜單入口只對(duì)屬于“人事管理”角色的用戶顯示,對(duì)其他用戶則隱藏。
圖 14. “訪問(wèn)被拒絕”頁(yè)面
圖 14是 AppFuse 提供的默認(rèn)“訪問(wèn)被拒絕”頁(yè)面,你可以通過(guò)修改 web\403.jsp 把它定制成自己喜歡的頁(yè)面。
事務(wù)控制
AppFuse 利用 Spring 的事務(wù)管理機(jī)制。Spring 可以以聲明的方式,對(duì)方法進(jìn)行事務(wù)控制,并且可以根據(jù)實(shí)際的需要,調(diào)整控制粒度。“聲明方式”的好處在于:核心代碼只需要關(guān)注業(yè)務(wù)邏輯,而將事務(wù)控制完全 交由配置文件管理,一方面是核心代碼簡(jiǎn)潔清晰,另一方面也便于進(jìn)行集中配置管理。
事務(wù)控制一般是定義在 service 類的方法上的。AppFuse 的所有 service 類都聲明在 src\service\applicationContext-service.xml 中,該文件中包含有一個(gè) “txProxyTemplate” bean 的聲明,它定義了基本事務(wù)策略。其它的 service 類從 “txProxyTemplate” 繼承,并可以“重寫”事務(wù)策略。例如,AppFuse 對(duì) userManager 的聲明如下:
| <!-- Transaction template for Managers, from: http://blog.exis.com/colin/archives/2004/07/31/concise-transaction-definitions-spring-11/ --> |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| <bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="transactionManager"/> <property name="transactionAttributes"> <props> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="remove*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> <!-- Transaction declarations for business services. To apply a generic transaction proxy to |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| all managers, you might look into using the BeanNameAutoProxyCreator --> <bean id="userManager" parent="txProxyTemplate"> <property name="target"> <bean class="org.appfuse.service.impl.UserManagerImpl"> <property name="userDao" ref="userDao"/> </bean> </property> <!-- Override default transaction attributes b/c of UserExistsException --> <property name="transactionAttributes"> <props> <prop key="save*">PROPAGATION_REQUIRED,-UserExistsException</prop> <prop key="remove*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> <!-- This property is overriden in applicationContext-security.xml to add method-level role security --> <property name="preInterceptors"> <list> <ref bean="userSecurityInterceptor"/> </list> </property> </bean> |
Spring 提供了大量的參數(shù)和選項(xiàng)使開(kāi)發(fā)者能夠靈活地管理事務(wù)。有關(guān) Spring 使用方面的知識(shí),請(qǐng)參閱 Spring 的文檔。另外,《Spring in Action》也是一個(gè)不錯(cuò)的選擇。
日志
AppFuse 集成了 Log4j 進(jìn)行日志管理,log4j.properties 位于 web\WEB-INF\classes 目錄下。AppFuse 已經(jīng)在絕大多數(shù)基類(諸如,BasePage.java、BaseDaoHibernate.java 以及 BaseManager.java 等)中加入了如下用于輸出日志的成員變量:
| protected final Log log = LogFactory.getLog(getClass()); |
因此,開(kāi)發(fā)者只需要在自己的代碼中調(diào)用 log 的方法就可以了,例如:“l(fā)og.debug("entered 'delete' method");”。
郵件
AppFuse 集成了 Spring 的發(fā)送郵件的功能。發(fā)送郵件需要用的參數(shù),如主機(jī)、端口等信息在 web\WEB-INF\classes\mail.properties 中進(jìn)行配置。和發(fā)送郵件相關(guān)的 bean 已經(jīng)在 applicationContext-service.xml 中聲明:mailEngine、mailSender、velocityEngine 以及 mailMessage。用戶只需要在自己的類中 “注入” mainSender 的實(shí)例,就可以發(fā)送郵件了。具體使用方法,請(qǐng)參閱Spring的文檔。
緩存
AppFuse 對(duì)緩存機(jī)制的支持源自 Hibernate 對(duì)緩存的支持。Hibernate 提供了對(duì)五種緩存機(jī)制的集成,AppFuse 默認(rèn)提供了其中的兩種:Ehcache 和 Oscache。開(kāi)發(fā)者也可以根據(jù)需要自行添加和配置。Acegi 默認(rèn)提供了對(duì) Ehcache 支持的實(shí)現(xiàn),所以 Ehcache 是較好的選擇。ehcache.xml 和 oscache.properties 位于 web\WEB-INF\classes 中。
|
結(jié)束語(yǔ)
使用 AppFuse 創(chuàng)建 Web 應(yīng)用,步驟非常簡(jiǎn)單,你只需要了解如何運(yùn)行 Ant 就能夠使用 AppFuse;使用 AppFuse 創(chuàng)建 Web 應(yīng)用,非常快速,因?yàn)?AppFuse 已經(jīng)幫我們完成大部分代碼生成/集成/配置的工作;使用 AppFuse 創(chuàng)建 Web 應(yīng)用,非常省力,因?yàn)?AppFuse 已經(jīng)提供了很多“開(kāi)箱即用”的功能。體驗(yàn)快速開(kāi)發(fā),從 AppFuse 開(kāi)始。
|
下載
| myapp.zip | 3531KB | HTTP |
| 關(guān)于下載方法的信息 | ||||
參考資料
學(xué)習(xí)- AppFuse:AppFuse 項(xiàng)目主頁(yè)。
- 使用 AppFuse 的七個(gè)理由(developerWorks,2006 年 8 月):來(lái)自項(xiàng)目創(chuàng)始人關(guān)于 AppFuse 的特性、架構(gòu)以及為什么要使用 AppFuse 的介紹。
- AppFuse Demos:AppFuse 演示和視頻
- AppFuse 快速入門指南:快速入門并使用 AppFuse。
- AppFuse 教程:深入學(xué)習(xí)更多有關(guān)使用 AppFuse 的知識(shí)。
- CSS Framework:了解更多 AppFuse 中使用到的 CSS Framework 的知識(shí)。
獲得產(chǎn)品和技術(shù)
- Ant:下載并學(xué)習(xí)如何使用 Ant。
- Eclipse:下載并學(xué)習(xí)如何使用 Eclipse。
- Tomcat:下載并學(xué)習(xí)如何使用 Tomcat。
- MySQL:下載并學(xué)習(xí)如何使用 MySQL。
- Tapestry:優(yōu)秀的 Web 框架。
- Spring:強(qiáng)大的輕量級(jí)容器。
- Hibernate:杰出的 ORM 持久化框架。
- Acegi:了解和學(xué)習(xí)如何用 Acegi 進(jìn)行系統(tǒng)安全配置。
關(guān)于作者
沈銳在 J2EE 項(xiàng)目開(kāi)發(fā)方面有多年的經(jīng)驗(yàn),目前在 IBM CSDL 從事 IBM Workplace Dashboard Framework 產(chǎn)品的開(kāi)發(fā)工作。他對(duì) Java 的開(kāi)源技術(shù)有著濃厚的興趣,歡迎使用 shenrui@cn.ibm.com 與他交流。 | ||
總結(jié)
以上是生活随笔為你收集整理的【转】 使用 AppFuse 快速构建 J2EE 应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: BAPI_PO_CHANGE修改NETP
- 下一篇: 两个整形变量,不用中间变量进行替换!