<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    2006年6月16日

    開始學(xué)習(xí)在 Java&S482; 平臺上使用諸如 Spring、Hibernate 或 MySQL 之類的開放源碼工具時(shí)可能非常困難。再加上 Ant 或 Maven,以及與 DWR 一起的小 Ajax,還有 Web 框架 —— 即 JSF,我們必須睜大眼睛盯著如何配置應(yīng)用程序。AppFuse 減少了集成開放源碼項(xiàng)目的痛苦。它可以把測試變成一等公民,讓我們可以從數(shù)據(jù)庫表生成整個(gè) UI,并使用 XFire 來支持 Web 服務(wù)。另外,AppFuse 的社區(qū)也非常健全,這是不同 Web 框架用戶可以一起融洽相處的地方之一。

    AppFuse 是一個(gè)開放源碼的項(xiàng)目和應(yīng)用程序,它使用了在 Java 平臺上構(gòu)建的開放源碼工具來幫助我們快速而高效地開發(fā) Web 應(yīng)用程序。我最初開發(fā)它是為了減少在為客戶構(gòu)建新 Web 應(yīng)用程序時(shí)所花費(fèi)的那些不必要的時(shí)間。從核心上來說,AppFuse 是一個(gè)項(xiàng)目骨架,類似于通過向?qū)?chuàng)建新 Web 項(xiàng)目時(shí) IDE 所創(chuàng)建的東西。當(dāng)我們使用 AppFuse 創(chuàng)建一個(gè)項(xiàng)目時(shí),它會提示我們將使用開放源碼框架,然后才創(chuàng)建項(xiàng)目。它使用 Ant 來驅(qū)動測試、代碼生成、編譯和部署。它提供了目錄和包結(jié)構(gòu),以及開發(fā)基于 Java 語言的 Web 應(yīng)用程序所需要的庫。

    與大部分 “new project” 向?qū)Р煌珹ppFuse 創(chuàng)建的項(xiàng)目從最開始就包含很多類和文件。這些文件用來實(shí)現(xiàn)特性,不過它們同時(shí)也會在您開發(fā)應(yīng)用程序時(shí)被用作示例。通過使用 AppFuse 啟動新項(xiàng)目,我們通??梢詼p少一到兩周的開發(fā)時(shí)間。我們不用擔(dān)心如何將開放源碼框架配置在一起,因?yàn)檫@都已經(jīng)完成了。我們的項(xiàng)目都已提前配置來與數(shù)據(jù)庫進(jìn)行交互,它會部署到應(yīng)用服務(wù)器上,并對用戶進(jìn)行認(rèn)證。我們不必實(shí)現(xiàn)安全特性,因?yàn)檫@都早已集成了。

    當(dāng)我最初開發(fā) AppFuse 時(shí),它只支持 Struts 和 Hibernate。經(jīng)過幾年的努力,我發(fā)現(xiàn)了比 Struts 更好的 Web 框架,因此我還添加了為這些 Web 框架使用的選項(xiàng)。現(xiàn)在,AppFuse 可以支持 Hibernate 或 iBATIS 作為持久性框架。對于 Web 框架來說,我們可以使用 JavaServer Faces(JSF)、Spring MVC、Struts、Tapestry 或 WebWork。

    AppFuse 提供了很多應(yīng)用程序需要的一些特性,包括:

    • 認(rèn)證和授權(quán)
    • 用戶管理
    • Remember Me(這會保存您的登錄信息,這樣就不用每次都再進(jìn)行登錄了)
    • 密碼提醒
    • 登記和注冊
    • SSL 轉(zhuǎn)換
    • E-mail
    • URL 重寫
    • 皮膚
    • 頁面修飾
    • 模板化布局
    • 文件上載

    這種 “開箱即用” 的功能是 AppFuse 與其他 CRUD 代 框架的區(qū)別之一(CRUD 取自創(chuàng)建、檢索、更新刪除 幾個(gè)操作的英文首字母),包括 Ruby on Rails、Trails 和 Grails。上面提到的這些框架,以及 AppFuse,都讓我們可以從數(shù)據(jù)庫表或現(xiàn)有的模型對象中生成主頁/細(xì)節(jié)頁。

    圖 1 闡述了一個(gè)典型 AppFuse 應(yīng)用程序的概念設(shè)計(jì):


    圖 1. 典型的 AppFuse 應(yīng)用程序
    典型的 AppFuse 應(yīng)用程序

    清單 1 給出了我們在創(chuàng)建 devworks 項(xiàng)目時(shí)所使用的命令行交互操作,同時(shí)還給出了所生成的結(jié)果。這個(gè)項(xiàng)目使用了 WebWork 作為自己的 Web 框架(請參考下面 參考資料 一節(jié)給出的鏈接)。


    清單 1. 使用 AppFuse 創(chuàng)建新項(xiàng)目
    alotta:~/dev/appfuse mraible$ ant new
                Buildfile: build.xml
                clean:
                [echo] Cleaning build and distribution directories
                init:
                new:
                [echo]
                [echo] +-------------------------------------------------------------+
                [echo] |    -- Welcome to the AppFuse New Application Wizard! --     |
                [echo] |                                                             |
                [echo] | To create a new application, please answer the following    |
                [echo] | questions.                                                  |
                [echo] +-------------------------------------------------------------+
                [input] What would you like to name your application [myapp]?
                devworks
                [input] What would you like to name your database [mydb]?
                devworks
                [input] What package name would you like to use [org.appfuse]?
                com.ibm
                [input] What web framework would you like to use [webwork,tapestry,spring,js
                f,struts]?
                webwork
                [echo] Creating new application named 'devworks'...
                [copy] Copying 359 files to /Users/mraible/Work/devworks
                [copy] Copying 181 files to /Users/mraible/Work/devworks/extras
                [copy] Copying 1 file to /Users/mraible/Work/devworks
                [copy] Copying 1 file to /Users/mraible/Work/devworks
                install:
                [echo] Copying WebWork JARs to ../../lib
                [copy] Copying 6 files to /Users/mraible/Work/devworks/lib
                [echo] Adding WebWork entries to ../../lib.properties
                [echo] Adding WebWork classpath entries
                [echo] Removing Struts-specific JARs
                [delete] Deleting directory /Users/mraible/Work/devworks/lib/struts-1.2.9
                [delete] Deleting directory /Users/mraible/Work/devworks/lib/strutstest-2.1.3
                [echo] Deleting struts_form.xdt for XDoclet
                [delete] Deleting directory /Users/mraible/Work/devworks/metadata/templates
                [echo] Deleting Struts merge-files in metadata/web
                [delete] Deleting 7 files from /Users/mraible/Work/devworks/metadata/web
                [echo] Deleting unused Tag Libraries and Utilities
                [delete] Deleting 2 files from /Users/mraible/Work/devworks/src/web/org/appfu
                se/webapp
                [echo] Modifying appgen for WebWork
                [copy] Copying 12 files to /Users/mraible/Work/devworks/extras/appgen
                [echo] Replacing source and test files
                [delete] Deleting directory /Users/mraible/Work/devworks/src/web/org/appfuse/
                webapp/form
                [delete] Deleting directory /Users/mraible/Work/devworks/src/web/org/appfuse/
                webapp/action
                [copy] Copying 13 files to /Users/mraible/Work/devworks/src
                [delete] Deleting directory /Users/mraible/Work/devworks/test/web/org/appfuse
                /webapp/form
                [delete] Deleting directory /Users/mraible/Work/devworks/test/web/org/appfuse
                /webapp/action
                [copy] Copying 5 files to /Users/mraible/Work/devworks/test
                [echo] Replacing web files (images, scripts, JSPs, etc.)
                [delete] Deleting 1 files from /Users/mraible/Work/devworks/web/scripts
                [copy] Copying 34 files to /Users/mraible/Work/devworks/web
                [delete] Deleting: /Users/mraible/Work/devworks/web/WEB-INF/validator-rules-c
                ustom.xml
                [echo] Modifying Eclipse .classpath file
                [echo] Refactoring build.xml
                [echo] ----------------------------------------------
                [echo] NOTE: It's recommended you delete extras/webwork as you shouldn't ne
                ed it anymore.
                [echo] ----------------------------------------------
                [echo] Repackaging info written to rename.log
                [echo]
                [echo] +-------------------------------------------------------------+
                [echo] |           -- Application created successfully! --           |
                [echo] |                                                             |
                [echo] | Now you should be able to cd to your application and run:   |
                [echo] | > ant setup test-all                                        |
                [echo] +-------------------------------------------------------------+
                BUILD SUCCESSFUL
                Total time: 15 seconds

    為什么使用 WebWork?
    Struts 社區(qū)最近在熱情地?fù)肀?WebWork,這種結(jié)合導(dǎo)致為 Java 平臺提供了一個(gè)非常優(yōu)秀的新 Web 框架:Struts 2。當(dāng)然,Spring MVC 是一個(gè)非常優(yōu)秀的基于請求的框架,但是它不能像 Struts 2 一樣支持 JSF。基于內(nèi)容的框架(例如 JSF 和 Tapestry)也都很好,但是我發(fā)現(xiàn) WebWork 更為直觀,更容易使用(更多有關(guān) Structs 2 和 JSF 的內(nèi)容請參看 參考資料)。

    在創(chuàng)建一個(gè)新項(xiàng)目之后,我們就得到了一個(gè)類似于圖 2 所示的目錄結(jié)構(gòu)。Eclipse 和 Intellij IDEA 項(xiàng)目文件都是作為這個(gè)過程的一部分創(chuàng)建的。


    圖 2. 項(xiàng)目的目錄結(jié)構(gòu)
    項(xiàng)目的目錄結(jié)構(gòu)

    這個(gè)目錄結(jié)構(gòu)與 Sun 為 Java 2 Platform Enterprise Edition(J2EE)Web 應(yīng)用程序推薦的目錄結(jié)構(gòu)非常類似。在 2.0 版本的 AppFuse 中,這個(gè)結(jié)構(gòu)會變化成適合 Apache Maven 項(xiàng)目的標(biāo)準(zhǔn)目錄結(jié)構(gòu)(有關(guān)這兩個(gè)目錄介紹的內(nèi)容,請參看 參考資料 中的鏈接)。AppFuse 還會從 Ant 遷移到 Maven 2 上,從而獲得相關(guān)下載的能力和對生成 IDE 項(xiàng)目文件的支持。目前基于 Ant 的系統(tǒng)要求提交者維護(hù)項(xiàng)目文件,而 Maven 2 可以通過簡單地使用項(xiàng)目的 pom.xml 文件生成 IDEA、Eclipse 和 NetBeans 項(xiàng)目文件。(這個(gè)文件位于您項(xiàng)目的根目錄中,是使用 Maven 構(gòu)建應(yīng)用程序所需要的主要組件)。它與利用 Ant 所使用的 build.xml 文件非常類似。)

    現(xiàn)在我們對 AppFuse 是什么已經(jīng)有一點(diǎn)概念了,在本文剩下的部分中,我們將介紹使用 AppFuse 的 7 點(diǎn)理由。即使您選擇不使用 AppFuse 來開始自己的項(xiàng)目,也會看到 AppFuse 可以為您提供很多樣板代碼,這些代碼可以在基于 Java 語言的 Web 應(yīng)用程序中使用。由于它是基于 Apache 許可證的,因此非常歡迎您在自己的應(yīng)用程序中重用這些代碼。

     1:測試技術(shù)

    測試是在軟件開發(fā)項(xiàng)目中很少被給予足夠信任的一個(gè)環(huán)節(jié)。注意我并不是說在軟件開發(fā)的一些刊物中沒有得到足夠的信任!很多文章和案例研究都給出了測試優(yōu)先的開發(fā)方式和足夠的測試覆蓋面以提高軟件的質(zhì)量。然而,測試通常都被看作是一件只會延長項(xiàng)目開發(fā)時(shí)間的事情。實(shí)際上,如果我們使用測試優(yōu)先的方法在編寫代碼之前就開始撰寫測試用例,我相信我們可以發(fā)現(xiàn)這實(shí)際上會加速 開發(fā)速度。另外,測試優(yōu)先也可以使維護(hù)和重用更加 容易。如果我們不編寫代碼來測試自己的代碼,那么就需要手工對應(yīng)用程序進(jìn)行測試 —— 這通常效率都不高。自動化才是關(guān)鍵。

    當(dāng)我們首次開始使用 AppFuse 時(shí),我們可能需要閱讀這個(gè)項(xiàng)目 Web 站點(diǎn)上提供的快速入門指南和教程(請參看 參考資料 中的鏈接)。這些教程的編寫就是為了您可以首先編寫測試用例;它們直到編寫接口和/或?qū)崿F(xiàn)之后才能編譯。如果您有些方面與我一樣,就會在開始編寫代碼之前就已經(jīng)編寫好測試用例了;這是真正可以加速編寫代碼的惟一方式。如果您首先編寫了代碼的實(shí)現(xiàn),通過某種方式驗(yàn)證它可以工作,那么您可能會對自己說,“哦,看起來不錯 —— 誰需要測試呢?我還有更多的代碼需要編寫!”這種情況不幸的一面是您通常都會做一些事情 來測試自己的代碼;您簡單地跳過了可以自動化進(jìn)行測試的地方。

    AppFuse 的文檔展示了如何測試應(yīng)用程序的所有 層次。它從數(shù)據(jù)庫層開始入手,使用了 DbUnit(請參看 參考資料)在運(yùn)行測試之前提前使用數(shù)據(jù)來填充自己的數(shù)據(jù)庫。在數(shù)據(jù)訪問(DAO)層,它使用了 Spring 的 AbstractTransactionalDataSourceSpringContextTests 類(是的,這的確是一個(gè)類的名字?。﹣碓试S簡單地加載 Spring 上下文文件。另外,這個(gè)類對每個(gè) testXXX() 方法封裝了一個(gè)事務(wù),并當(dāng)測試方法存在時(shí)進(jìn)行回滾。這種特性使得測試 DAO 邏輯變得非常簡單,并且不會對數(shù)據(jù)庫中的數(shù)據(jù)造成影響。

    在服務(wù)層,jMock (請參看 參考資料)用來編寫那些可以消除 DAO 依賴的真正 單元測試。這允許進(jìn)行驗(yàn)證業(yè)務(wù)邏輯正確的快速測試;我們不用擔(dān)心底層的持久性邏輯。

    HtmlUnit 支持
    HtmlUnit 團(tuán)隊(duì)在 1.8 發(fā)行版中已經(jīng)完成了相當(dāng)多的工作來確保包可以與流行的 Ajax 框架(Prototype 和 Scriptaculous)很好地工作。

    在 Web 層,測試會驗(yàn)證操作(Struts/WebWork)、控件(Spring MVC)、頁面(Tapestry)和管理 bean(JSF)如我們所期望的一樣進(jìn)行工作。Spring 的 spring-mock.jar 可以非常有用地用來測試所有這些框架,因?yàn)樗艘粋€(gè) Servlet API 的仿真實(shí)現(xiàn)。如果沒有這個(gè)有用的庫,那么測試 AppFuse 的 Web 框架就會變得非常困難。

    UI 通常是開發(fā) Web 應(yīng)用程序過程中最為困難的一部分。它也是顧客最經(jīng)常抱怨的地方 —— 這既是由于它并不是非常完美,也是由于它的工作方式與我們期望的并不一樣。另外,沒有什么會比在客戶面前作演示的過程中看到看到異常堆棧更糟糕的了!您的應(yīng)用程序可能會非??膳?,但是客戶可能會要求您做到十分完美。永遠(yuǎn)不要讓這種事情發(fā)生。Canoo WebTest 可以對 UI 進(jìn)行測試。它使用了 HtmlUnit 來遍歷測試 UI,驗(yàn)證所有的元素都存在,并可以填充表單的域,甚至可以驗(yàn)證一個(gè)假想的啟用 Ajax 的 UI 與我們預(yù)期的工作方式一樣。(有關(guān) WebTest 和 HTMLUnit 的鏈接請參看 參考資料。)

    為了進(jìn)一步簡化 Web 的測試,Cargo(請參看 參考資料)對 Tomcat 的啟動和停止(分別在運(yùn)行 WebTest 測試之前和之后)進(jìn)行了自動化。







     2:集成技術(shù)

    正如我在本文簡介中提到的一樣,很多開放源碼庫都已經(jīng)預(yù)先集成到 AppFuse 中了。它們可以分為以下幾類:

    • 編譯、報(bào)告和代碼生成:Ant、Ant Contrib Tasks、Checkstyle、EMMA、Java2Html、PMD 和 Rename Packages
    • 測試框架:DbUnit、Dumbster、jMock、JUnit 和 Canoo WebTest
    • 數(shù)據(jù)庫驅(qū)動程序:MySQL 和 PostgreSQL
    • 持久性框架:Hibernate 和 iBATIS
    • IoC 框架:Spring
    • Web 框架:JSF、Spring MVC、Struts、Tapestry 和 WebWork
    • Web 服務(wù):XFire
    • Web 工具:Clickstream、Display Tag、DWR、JSTL、SiteMesh、Struts Menu 和 URL Rewrite Filter
    • Security:Acegi Security
    • JavaScript 和 CSS:Scriptaculous、Prototype 和 Mike Stenhouse 的 CSS Framework

    除了這些庫之外,AppFuse 還使用 Log4j 來記錄日志,使用 Velocity 來構(gòu)建 e-mail 和菜單模板。Tomcat 可以支持最新的開發(fā),我們可以使用 1.4 或 5 版本的 Java 平臺來編譯或構(gòu)建程序。我們應(yīng)該可以將 AppFuse 部署到任何 J2EE 1.3 兼容的應(yīng)用服務(wù)器上;這已經(jīng)經(jīng)過了測試,我們知道它在所有主要版本的 J2EE 服務(wù)器和所有主要的 servlet 容器上都可以很好地工作。

    圖 3 給出了上面創(chuàng)建的 devworks 項(xiàng)目的 lib 目錄。這個(gè)目錄中的 lib.properties 文件控制了每個(gè)依賴性的版本號,這意味著我們可以簡單地通過把這些包的新版本放到這個(gè)目錄中并執(zhí)行諸如 ant test-all -Dspring.version=2.0 之類的命令來測試這些包的新版本。


    圖3. 項(xiàng)目依賴性
    AppFuse 項(xiàng)目依賴性

    預(yù)先集成這些開放源碼庫可以在項(xiàng)目之初極大地提高生產(chǎn)效率。盡管我們可以找到很多文檔介紹如何集成這些庫,但是定制工作示例并簡單地使用它來開發(fā)應(yīng)用程序要更加簡單。

    除了可以簡化 Web 應(yīng)用程序的開發(fā)之外,AppFuse 讓我們還可以將 Web 服務(wù)簡單地集成到自己的項(xiàng)目中。盡管 XFire 也在 AppFuse 下載中一起提供了,不過如果我們希望,也可以自己集成 Apache Axis(請參看 參考資料 中有關(guān) Axis 集成的教程)。另外,Spring 框架和 XFire 可以一起將服務(wù)層作為 Web 服務(wù)非常簡單地呈現(xiàn)出來,這就為我們提供了開發(fā)面向服務(wù)架構(gòu)的能力。

    另外,AppFuse 并不會將我們限定到任何特定的 API 上。它只是簡單地對可用的最佳開放源碼解決方案重新進(jìn)行打包和預(yù)先集成。AppFuse 中的代碼可以處理這種集成,并實(shí)現(xiàn)了 AppFuse 的基本安全性和可用性特性。只要可能,就會減少代碼,以便向 AppFuse 的依賴框架添加一個(gè)特性。例如,AppFuse 自帶的 Remember Me 和 SSL 切換特性最近就因?yàn)轭愃频奶匦远鴱?Acegi Security 中刪除了。







    3:自動化技術(shù)

    Ant 使得簡化了從編譯到構(gòu)建再到部署的自動化過程。Ant 是 AppFuse 中的一等公民,這主要是因?yàn)槲野l(fā)現(xiàn)在命令行中執(zhí)行操作比從 IDE 中更加簡單。我們可以使用 Ant 實(shí)現(xiàn)編譯、測試、部署和執(zhí)行任何代碼生成的任務(wù)。

    盡管這種能力對于有些人來說非常重要,但是它并不適用于所有的人。很多 AppFuse 用戶目前都使用 Eclipse 或 Intellij IDEA 來構(gòu)建和測試自己的項(xiàng)目。在這些 IDE 中運(yùn)行 Ant 的確可以工作,但是這樣做的效率通常都不如使用 IDE 內(nèi)置的 JUnit 支持來運(yùn)行測試效率高。

    幸運(yùn)的是,AppFuse 支持在 IDE 中運(yùn)行測試,不過管理這種特性對于 AppFuse 開發(fā)人員來說就變得非常困難了。最大的痛苦在于 XDoclet 用來生成 Hibernate 映射文件和 Web 框架所使用的一些工件(例如 ActionForms 和 Struts 使用的 struts-config.xml)。IDE 并不知道需要生成的代碼,除非我們配置使用 Ant 來編譯它們,或者安裝了一些可以認(rèn)識 XDoclet 的插件。

    這種對知識的缺乏是 AppFuse 2.0 切換到 JDK 5 和 Maven 2 上的主要原因。JDK 5、注釋和 Struts 2 將讓我們可以擺脫 XDoclet。Maven 2 將使用這些生成的文件和動態(tài)類路徑來生成 IDE 項(xiàng)目文件,這樣對項(xiàng)目的管理就可以進(jìn)行簡化。目前基于 Ant 的編譯系統(tǒng)已經(jīng)為不同的層次生成了一些工件(包括 dao.jar、service.jar 和 webapp.war),因此切換到 Maven 的模型上應(yīng)該是一個(gè)非常自然的調(diào)整。

    除了 Ant 之外(它對于編譯、測試、部署和報(bào)告具有豐富的支持),對于 CruiseControl 的支持也構(gòu)建到了 AppFuse 中。CruiseControl 是一個(gè) Continuous Integration 應(yīng)用程序,讓我們可以在源代碼倉庫中代碼發(fā)生變化時(shí)自動運(yùn)行所有的測試。extras/cruisecontrol 目錄包含了我們?yōu)榛?AppFuse 的項(xiàng)目快速、簡單地設(shè)置 Continuous Integration 時(shí)所需要的文件。

    設(shè)置 Continuous Integration 是軟件開發(fā)周期中我們首先要做的事情之一。它不但激發(fā)程序員去編寫測試用例,而且還通過 “You broke the build!” 游戲促進(jìn)了團(tuán)隊(duì)之間的合作和融合。







    4:安全特性和可擴(kuò)展性

    AppFuse 最初是作為我為 Apress 編寫的書籍 Pro JSP 中示例應(yīng)用程序的一部分開發(fā)的。這個(gè)示例應(yīng)用程序展示了很多安全特性和用于簡化 Struts 開發(fā)的特性。這個(gè)應(yīng)用程序中的很多安全特性在 J2EE 的安全框圖中都不存在。使用容器管理認(rèn)證(CMA)的認(rèn)證方法非常簡單,但是 Remember Me、密碼提示、SSL 切換、登記和用戶管理等功能卻都不存在。另外,基于角色的保護(hù)方法功能在非 EJB 環(huán)境中也是不可能的。

    最初,AppFuse 使用自己的代碼和用于 CMA 的解決方案完全實(shí)現(xiàn)了這些特性。我在 2004 年年初開始學(xué)習(xí) Spring 時(shí)就聽說過有關(guān) Acegi Security 的知識。我對 Acegi 所需要的 XML 的行數(shù)(175)與 web.xml 中所需要的 CMA 的行數(shù)(20)進(jìn)行了比較,很快就決定丟棄 Acegi 了,因?yàn)樗^復(fù)雜了。

    一年半之后 —— 在為另外一本書 Spring Live 中編寫了一章有關(guān)使用 Acegi Security 的內(nèi)容之后 —— 我就改變了自己的想法。Acegi 的確(目前仍然)需要很多 XML,但是一旦我們理解了這一點(diǎn),它實(shí)際上是相當(dāng)簡單的。當(dāng)我們最終作出改變,使用 Acegi Security 的特性來全部取代 AppFuse 的特性之后,我們最終刪除了大量的代碼。類之上的類都已經(jīng)沒有了,“Acegi handles that now” 中消失的部分現(xiàn)在全部進(jìn)入了 CVS 的 Attic 中了。

    Acegi Security 是 J2EE 安全模型中曾經(jīng)出現(xiàn)過的最好模型。它讓我們可以實(shí)現(xiàn)很多有用的特性,這些特性在 Servlet API 的安全模型中都不存在:認(rèn)證、授權(quán)、角色保護(hù)方法、Remember Me、密碼加密、SSL 切換、用戶切換和注銷。它讓我們還可以將用戶證書存儲到 XML 文件、數(shù)據(jù)庫、LDAP 或單點(diǎn)登錄系統(tǒng)(例如 Yale 的 Central Authentication Service (CAS) 或者 SiteMinder)中。

    AppFuse 對很多與安全性相關(guān)的特性的實(shí)現(xiàn)從一開始都是非常優(yōu)秀的?,F(xiàn)在 AppFuse 使用了 Acegi Security,這些特性 —— 以及更多特性 —— 都非常容易實(shí)現(xiàn)。Acegi 有很多地方都可以進(jìn)行擴(kuò)充:這是它使用巨大的 XML 配置文件的原因。正如我們已經(jīng)通過去年的課程對 Acegi 進(jìn)行集成一樣,我們已經(jīng)發(fā)現(xiàn)對很多 bean 的定義進(jìn)行定制可以更加緊密地與 AppFuse 建立聯(lián)系。

    Spring IoC 容器和 Acegi Security 所提供的簡單開發(fā)、容易測試的代碼和松耦合特性的組合是 AppFuse 是這么好的一種開發(fā)平臺的主要原因。這些框架都是不可插入的,允許生成干凈的可測試代碼。AppFuse 集成了很多開放源碼項(xiàng)目,依賴注入允許對應(yīng)用程序?qū)舆M(jìn)行簡單的集成。






    5:使用 AppGen 生成代碼

    有些人會將代碼生成稱為代碼氣味的散播(code smell)。在他們的觀點(diǎn)中,如果我們需要生成代碼,那么很可能就會做一些錯事。我傾向于這種確定自己代碼使用的模式和自動化生成代碼的能力應(yīng)該稱為代碼香味的彌漫(code perfume)。如果我們正在編寫類似的 DAO、管理器、操作或控件,并且不想為它們生成代碼,那么這就需要根據(jù)代碼的氣味來生成代碼。當(dāng)然,當(dāng)語言可以為我們提供可以簡化任務(wù)的特性時(shí),一切都是那么美好;不過代碼生成通常都是一個(gè)必需 —— 通常其生產(chǎn)率也非常高 —— 的任務(wù)。

    AppFuse 中提供了一個(gè)基于 Ant 和 XDoclet 的代碼生成工具,名叫 AppGen。默認(rèn)情況下,常見的 DAO 和管理器都可以允許我們對任何普通老式 Java 對象(POJO)進(jìn)行 CRUD 操作,但是在 Web 層上這樣做有些困難。AppGen 有幾個(gè)特性可以用來執(zhí)行以下任務(wù):

    • (使用 Middlegen 和 Hibernate 工具)從數(shù)據(jù)庫表中生成 POJO
    • 從 POJO 生成 UI
    • 為 DAO、管理器、操作/控制器和 UI 生成測試

    在運(yùn)行 AppGen 時(shí),您會看到提示說 AppGen 要從數(shù)據(jù)庫表或 POJO 中生成代碼。如果在命令行中執(zhí)行 ant install-detailed,AppGen 就會安裝 POJO 特定的 DAO、管理器以及它們的測試。運(yùn)行 ant install 會導(dǎo)致 Web 層的類重用通用的 DAO 和默認(rèn)存在的管理器。

    為了闡述 AppGen 是如何工作的,我們在 devworks MySQL 數(shù)據(jù)庫中創(chuàng)建了如清單 2 所示的表:


    清單 2. 創(chuàng)建一個(gè)名為 cat 的數(shù)據(jù)庫表
        create table cat (
                cat_id int(8) auto_increment,
                color varchar(20) not null,
                name varchar(20) not null,
                created_date datetime not null,
                primary key (cat_id)
                ) type=InnoDB;
                

    在 extras/appgen 目錄中,運(yùn)行 ant install-detailed。這個(gè)命令的輸出結(jié)果對于本文來說實(shí)在太長了,不過我們在清單 3 中給出了第一部分的內(nèi)容:


    清單 3. 運(yùn)行 AppGen 的 install-detailed 目標(biāo)
    $ ant install-detailed
                Buildfile: build.xml
                init:
                [mkdir] Created dir: /Users/mraible/Work/devworks/extras/appgen/build
                [echo]
                [echo] +-------------------------------------------------------+
                [echo] |             -- Welcome to the AppGen! --              |
                [echo] |                                                       |
                [echo] | Use the "install" target to use the generic DAO and   |
                [echo] | Manager, or use "install-detailed" to general a DAO   |
                [echo] | and Manager specifically for your model object.       |
                [echo] +-------------------------------------------------------+
                [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)?
                cat
                [input] What is the name, if any, of the module for your table (i.e. organization)?
                [echo] Running Middlegen to generate POJO...
                

    要對 cat 表使用這個(gè)新生成的代碼,我們需要修改 src/dao/com/ibm/dao/hibernate/applicationContext-hibernate.xml,來為 Hibernate 添加 Cat.hbm.xml 映射文件。清單 3 給出了我們修改后的 sessionFactory bean 的樣子:


    清單 4. 將 Cat.hbm.xml 添加到 sessionFactory bean 中
        <bean id="sessionFactory" class="...">
                <property name="dataSource" ref="dataSource"/>
                <property name="mappingResources">
                <list>
                <value>com/ibm/model/Role.hbm.xml</value>
                <value>com/ibm/model/User.hbm.xml</value>
                <value>com/ibm/model/Cat.hbm.xml</value>
                </list>
                </property>
                ...
                </bean>
                

    在運(yùn)行 ant setup deploy 之后,我們就應(yīng)該可以在部署的應(yīng)用程序中對 cat 表執(zhí)行 CRUD 操作了:


    圖 4. Cat 列表
    所生成的主屏幕

    圖 5. Cat 表單
    所生成的詳細(xì)屏幕

    我們在上面的屏幕快照中看到的記錄都是作為代碼生成的一部分創(chuàng)建的,因此現(xiàn)在就有測試數(shù)據(jù)了。







    6:文檔

    我們可以找到 AppFuse 各個(gè)風(fēng)味的教程,并且它們都以 6 種不同的語言給出了:中文、德語、英語、韓語、葡萄牙語和西班牙語。使用風(fēng)味(flavor) 一詞,我的意思是不同框架的組合,例如 Spring MVC 加上 iBATIS、Spring MVC 加上 Hibernate 或 JSF 加上 Hibernate。使用這 5 種 Web 框架和兩種持久框架,可以有好幾種組合。有關(guān)它們的翻譯,AppFuse 為自己的默認(rèn)特性提供了 8 種翻譯??捎谜Z言包括中文、荷蘭語、德語、英語、法語、意大利語、葡萄牙語和西班牙語。

    除了核心教程之外,還添加了很多教程(請參看 參考資料) 來介紹與各種數(shù)據(jù)庫、應(yīng)用服務(wù)器和其他開放源碼技術(shù)(包括 JasperReports、Lucene、Eclipse、Drools、Axis 和 DWR)的集成。







    7:社區(qū)

    Apache 軟件基金會對于開放源碼有一個(gè)有趣的看法。它對圍繞開放源碼項(xiàng)目開發(fā)一個(gè)開放源碼社區(qū)最感興趣。它的成員相信如果社區(qū)非常強(qiáng)大,那么產(chǎn)生高質(zhì)量的代碼就是一個(gè)自然的過程。下面的內(nèi)容引自 Apache 主頁:

    “我們認(rèn)為自己不僅僅是一組共享服務(wù)器的項(xiàng)目,而且是一個(gè)開發(fā)人員和用戶的社區(qū)。”

    AppFuse 社區(qū)從 2003 年作為 SourceForge 上的一個(gè)項(xiàng)目(是 struts.sf.net 的一部分)啟動以來,已經(jīng)獲得了極大的增長。通過在 2004 年 3 月轉(zhuǎn)換到 java.net 上之后,它已經(jīng)成為這里一個(gè)非常流行的項(xiàng)目,從 2005 年 1 月到 3 月成為訪問量最多的一個(gè)項(xiàng)目。目前它仍然是一個(gè)非常流行的項(xiàng)目(有關(guān) java.net 項(xiàng)目統(tǒng)計(jì)信息的鏈接,請參看 參考資料),不過在這個(gè)站點(diǎn)上它正在讓位于 Sun 贊助的很多項(xiàng)目。

    在 2004 年年末,Nathan Anderson 成為繼我之后第一個(gè)提交者。此后有很多人都加入了進(jìn)來,包括 Ben Gill、David Carter、Mika G?ckel、Sanjiv Jivan 和 Thomas Gaudin。很多現(xiàn)有的提交者都已經(jīng)通過各種方式作出了自己的貢獻(xiàn),他們都幫助 AppFuse 社區(qū)成為一個(gè)迅速變化并且非常有趣的地方。

    郵件列表非常友好,我們試圖維護(hù)這樣一條承諾 “沒有問題是沒有人理會的問題”。我們的郵件列表歸檔文件中惟一一條 “RTFM” 是從用戶那里發(fā)出的,而不是從開發(fā)者那里發(fā)出的。我們絕對信奉 Apache 開放源碼社區(qū)的哲學(xué)。引用我最好的朋友 Bruce Snyder 的一句話,“我們?yōu)榇a而來,為人們而留下”。目前,大部分開發(fā)者都是用戶,我們通常都喜歡有一段美妙的時(shí)間。另外,大部分文檔都是由社區(qū)編寫的;因此,這個(gè)社區(qū)的知識是非常淵博的。







    結(jié)束語

    我們應(yīng)該嘗試使用 AppFuse 進(jìn)行開發(fā),這是因?yàn)樗试S我們簡單地進(jìn)行測試、集成、自動化,并可以安全地生成 Web 應(yīng)用程序。其文檔非常豐富,社區(qū)也非常友好。隨著其支撐框架越來越好,AppFuse 也將不斷改進(jìn)。

    從 AppFuse 2.0 開始,我們計(jì)劃遷移到 JDK 5(仍然支持部署到 1.4)和 Maven 2 上去。這些工具可以簡化使用 AppFuse 的開發(fā)、安裝和升級。我們計(jì)劃充分利用 Maven 2 的功能來處理相關(guān)依賴性。我們將碰到諸如 appfuse-hibernate-2.0.jar 和 appfuse-jsf-2.0.jar 之類的工件。這些工件都可以在 pom.xml 文件中進(jìn)行引用,它們負(fù)責(zé)提取其他相關(guān)依賴性。除了在自己的項(xiàng)目中使用 AppFuse 基類之外,我們還可以像普通的框架一樣在 JAR 中對這些類簡單地進(jìn)行擴(kuò)展,這應(yīng)該會大大簡化它的升級過程,并鼓勵更多用戶將自己希望的改進(jìn)提交到這個(gè)項(xiàng)目中。

    如果沒有其他問題,使用 AppFuse 可以讓您始終處于 Java Web 開發(fā)的技術(shù)前沿上 —— 就像我們一樣!



    參考資料

    學(xué)習(xí)

    獲得產(chǎn)品和技術(shù)
    • AppFuse on java.net:下載不同風(fēng)味的 AppFuse。

    • WebWork:了解這個(gè)易于使用的 Web 框架。

    • DbUnit:查看更多有關(guān) JUnit 擴(kuò)展的內(nèi)容。

    • jMock:創(chuàng)建動態(tài)仿真對象來簡化真正的單元測試。

    • Canoo WebTest:自動化 Web 應(yīng)用程序的 UI 測試。

    • HtmlUnit:WebTest 的優(yōu)秀 JavaScript 支持背后的基礎(chǔ)。

    • Cargo:自動啟動和停止容器。

    • Greenbox:一種代碼生成框架。


    討論


    關(guān)于作者

    Matt Raible 居住在美國科羅拉多州的丹佛,他在那里是 Spring 和 Web 框架對 Virtuas Open Source Solutions 的實(shí)踐先驅(qū)。他在開放源碼領(lǐng)域具有豐富的經(jīng)驗(yàn),是這個(gè)領(lǐng)域的專家。他在這個(gè)領(lǐng)域中既是用戶,又是一名開發(fā)人員。Matt 是 SourceBeat PublishingSpring Live 的作者。他還為 Apress 的書籍 Pro JSP Third Edition 作出了很大的貢獻(xiàn)。他是很多開放源碼會議的積極倡導(dǎo)者,包括 ApacheCon、MySQL User's Conference 和 OSCON,同時(shí)他還是 http://raibledesigns.com/ 上一名非?;钴S的博客。Raible 的大部分生活都被計(jì)算機(jī)所包圍了,盡管他是在連電都沒有的 Montana 長大的。當(dāng)不工作的時(shí)候時(shí),他總是試圖讓妻子 Julie 成為世界上最幸福的女人,或者與他們的孩子 Abbie 和 Jack 一起玩耍。

    posted @ 2007-07-31 11:17 戴生 閱讀(365) | 評論 (0)編輯 收藏
     

    displayTag作為當(dāng)前還算得上比較流行的表現(xiàn)層工具插件,在sourceForge官方網(wǎng)站(http://displaytag.sourceforge.net/)上,平均每天的訪問量數(shù)以萬計(jì),本文是建立在實(shí)際開發(fā)過程中
    碰到的導(dǎo)出excel報(bào)表的實(shí)際需求,所獲得的一些學(xué)習(xí)心得與技巧與大家分享.
    默認(rèn)的displayTag導(dǎo)出的Excel格式會有中文亂碼,網(wǎng)上大部分文章都說只有改一下,org.displaytag.export.ExcelView類中,
    public String getMimeType()
    {
    return "application/vnd.ms-excel"; //$NON-NLS-1$
    }
    方法,在方法后面追加;chartset=gbk;其它不盡然,如果這樣改的話在tomcat作為web服務(wù)端的話,如果列表中有中文,很慢很慢才會有導(dǎo)出(不過,我至今尚未在tomcat下導(dǎo)出過中文),
    把WEB應(yīng)用布署在JBOSS下面,導(dǎo)出的話,如果數(shù)據(jù)量大的話也會有20-40秒不等,后來到displayTag的官網(wǎng)上,去看它的bugtrack,發(fā)現(xiàn)其實(shí)不盡然。其它displayTag如果在你需要導(dǎo)出excel并且想自已利用apache的
    POI的話,要再去到官方網(wǎng)上下載一個(gè)displaytag-export-poi-1.1.jar的包,詳細(xì)操作請看http://displaytag.sourceforge.net/11/install.html

    其中里面談到,如果,每次導(dǎo)出的excel數(shù)據(jù)總是有緩存的話,可以在web.xml文件中加入如下配置進(jìn)行過濾,這樣就可以導(dǎo)出實(shí)時(shí)數(shù)據(jù)了。
    Configure the Filter in your web.xml:

    <filter>
    <filter-name>ResponseOverrideFilter</filter-name>
    <filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class>
    </filter>And add mappings for the pages that you will intercept, for example:

    <filter-mapping>
    <filter-name>ResponseOverrideFilter</filter-name>
    <url-pattern>*.do</url-pattern>
    </filter-mapping>
    <filter-mapping>
    <filter-name>ResponseOverrideFilter</filter-name>
    <url-pattern>*.jsp</url-pattern>
    </filter-mapping>

    從以上內(nèi)容來看,也只是告訴你,如果要用apache的最新的POI的話,需要把displaytag-export-poi-1.1.jar從官網(wǎng)下載下來,放入你的工程文件中,
    并沒有說如何調(diào)用寫自己的所需的excel的報(bào)表格式.下面就實(shí)際問題,來討論一下如何讓displayTag導(dǎo)出自己所需的excel格式.
    在displayTag所提供的接口類中,導(dǎo)出自已所需的Excel有兩種方式,一種是通過指定的excel模板,一種是對excel的所有的格子,一個(gè)個(gè)樣式的處理,
    后一種方式完全體現(xiàn)了“慢工出細(xì)活”的格言,而前一種方式實(shí)現(xiàn)起來顯然要好用得多,只用讀模板的樣式就行了。如何調(diào)用displayTag對導(dǎo)出自定制的Excel文件
    所提供的接口呢,請看下文,(不要急噢!^_^)
    要調(diào)用displayTag給Poi所提供的接口操作步驟如下:
    1,先要在你的appfuse工程中新建一個(gè)類,讓其實(shí)現(xiàn)org.displaytag.export.BinaryExportView接口,其中關(guān)鍵的方法是
    public void doExport(OutputStream out) throws JspException {
    String captionvalue = this.model.getCaption();
    // ExcelHssfView1 tempExcelView=new ExcelHssfView1();
    // try {
    // BeanUtils.setProperty(tempExcelView, "action",captionvalue);
    // } catch (IllegalAccessException e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // } catch (InvocationTargetException e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // }
    if (captionvalue != null) {
    captionvalue = captionvalue.replaceAll("(\\r)|(\\n)|(\\t)", "");

    doExportCommon(out);

    } else {
    System.out.println("exec Common");
    doExportCommon(out);
    }
    }
    對這個(gè)方法按照你的POI的定制excel報(bào)表的的方法,然后實(shí)現(xiàn)它,再把內(nèi)容寫入outputStream中去,基本上就可以了,當(dāng)然如果有上面的

    this.model.getCaption()是讀取displayTag的頁面標(biāo)簽<displayTag:caption/>標(biāo)簽中的內(nèi)容,可以在不同的JSP頁面放入不同的caption的值
    從而判斷調(diào)用不同的方法,生成不同的excel樣式的報(bào)表,靈活性兼而有之.
    寫完以上類以后,最好先寫個(gè)測試方法,用main或junit工具都成,看看你的調(diào)用poi的邏輯有沒有問題。
    當(dāng)以上的類及方法寫完后,就要在你的appfuse工程中找displaytag.properties文件了,一般就在web/class/目錄下,找到后,打開此文件,添加如下一段配置:
    export.excel.class=org.displaytag.export.excel.ExcelHssfView1
    后面一段是你的新建的類的文件的路徑
    因?yàn)槭嵌鄧Z言系統(tǒng),所以最好把display_en.properties及display_zh_Cn.properties都加上.
    到此就完成了,使用自己的POI來在appfuse中導(dǎo)出指定格式樣式的excel文件.先別急噢,還有更精彩的等著你。這個(gè)時(shí)候又有一個(gè)問題來了,如果你
    頁面想要顯示某些列表字段列,而導(dǎo)出的excel文件中又不出現(xiàn)這樣的字段,又該如何處理呢,嘿嘿,請接著看下文。
    如果要實(shí)現(xiàn)以上功能請如下操作:
    1,調(diào)整頁面上的displayTag標(biāo)簽的參數(shù)值,呵,比如:

    <display:table name="testList" cellspacing="0" cellpadding="0" requestURI="" sort="list"
    id="testList" pagesize="5" class="table testList" export="true"
    defaultsort="1" defaultorder="descending" >
    <display:caption media="excel">ExportByCommon</display:caption>
    <display:column title="ID" sortable="true" media="html">
    <a href="/aaa.html?id=<c:out value="${testList.id }" /> "
    target="operationFrame">
    <c:out value="${testList.id }" />
    </a>

    </display:column>
    <display:column title="Status" sortable="true" media="html">
    <img src="<c:out value="${testList.status}" />.gif" title="<c:out value="Status:${testList.status}" />">
    </display:column>

    <display:column property="remarks" escapeXml="true" sortable="true"
    title="Remarks" style="word-wrap: break-word;word-break: break-all; width:90px;"/>
    <display:footer media="excel">
    <c:out value="${aa }"></c:out>|
    <c:out value="(${bb })"></c:out>|
    <c:out value="${currentDate }"></c:out>
    </display:footer>
    <display:setProperty name="item_name" value="Info"/>
    <display:setProperty name="items_name" value="Infos"/>
    <display:setProperty name="export.excel" value="true" />
    <display:setProperty name="export.excel.filename" value="<%=exportFileName%>"/>
    <display:setProperty name="export.csv" value="false" />
    <display:setProperty name="export.xml" value="false" />
    <display:setProperty name="export.pdf" value="false" />
    </display:table>
    </form>
    注意上面用了多種配置需求,可以自已加鏈接,自定義導(dǎo)出名,自定義表頭表尾,自定義是否全排序,自定義樣式等,這些網(wǎng)上都有,就不細(xì)說了,
    關(guān)鍵的需求點(diǎn)media的配置參數(shù)噢,如果media="excel"表示只在excel中顯示,如果media=html表示僅在頁面出現(xiàn),沒有此參數(shù)是兩個(gè)都顯示噢
    其它的格式也類同設(shè)置,到此displayTag的點(diǎn)點(diǎn)心得分享與大家完畢,謝謝大家花費(fèi)時(shí)間分享我的快樂!^_^
    噢,上文提到中文問題,用POI后就解決了!

    posted @ 2007-07-31 11:12 戴生 閱讀(1351) | 評論 (0)編輯 收藏
     
         摘要: appfuse在eclipse下的入門  閱讀全文
    posted @ 2006-06-16 15:25 戴生 閱讀(4136) | 評論 (9)編輯 收藏
     
    主站蜘蛛池模板: 色www永久免费| 97无码免费人妻超级碰碰碰碰| 国产成人无码精品久久久免费| 一个人看的www在线免费视频| 无码av免费网站| 日韩视频免费一区二区三区| 亚洲国产精品日韩在线观看| 色屁屁在线观看视频免费| 日韩精品视频免费在线观看| 国产亚洲精品AAAA片APP| 国产美女被遭强高潮免费网站 | 亚洲成A人片在线观看无码3D| 久久国产精品亚洲一区二区| 国产成人亚洲综合a∨| a级毛片毛片免费观看久潮喷| 亚洲AV永久纯肉无码精品动漫| 免费观看男人吊女人视频| 亚洲黄网在线观看| 好男人www免费高清视频在线| 亚洲国产AV一区二区三区四区| 一区二区在线免费观看| 亚洲国产精品综合久久网各| 成人免费看黄20分钟| 久久精品国产亚洲av影院| 无人在线直播免费观看| 亚洲av成人无码网站…| 国产综合亚洲专区在线| 99精品在线免费观看| 亚洲一卡2卡三卡4卡无卡下载 | 久久成人a毛片免费观看网站| 亚洲日韩涩涩成人午夜私人影院| 亚洲免费视频一区二区三区| 婷婷亚洲综合五月天小说| 毛片免费全部免费观看| 一级毛片成人免费看a| 久久精品蜜芽亚洲国产AV| 国产青草视频在线观看免费影院| 精品乱子伦一区二区三区高清免费播放| 亚洲高清日韩精品第一区| 亚洲AⅤ无码一区二区三区在线| 亚洲精品无码专区在线播放|