svg_007

           

          2005年10月10日

          web應用(轉自Sun社區)

          Web應用是Web服務的一種動態擴展。Web應用可分為兩類:
          • ?面向表示的Web應用。在響應請求時,面向表示的Web應用產生動態的Web頁面,這種頁面包含了各種不同的標記語言(如HTML, XML, 等等)。
          • 面向服務的Web應用。面向服務的Web應用實現細粒度Web服務的端點。面向服務Web應用通常為面向表示應用所調用。

          在Java2平臺上,Web組件為Web 服務器提供了動態擴展能力。Web組件可以是Java Servlets或者JSP頁面。Servlets是Java編程語言中用于動態地處理請求和建立響應的一種類。JSP頁面是基于文本的文檔,它像 servlets一樣執行,但是允許使用更自然的方法來創建靜態內容。盡管servlet和JSP頁面可以交替地使用,但是它們各有千秋。 Servlets最適合于面向服務的Web應用,同時還擅長于管理面向表示的Web服務的控制功能,例如發送請求和處理非原文的數據。而JSP頁面則更適 合于產生基于文本的標記,例如:HTML、SVG、WML以及XML等。

          Web組件以一個名為Web容器 的運行時平臺中的服務作為支撐。在Java Web服務開發包(Java Web Services Developer Pack, Java WSDP)中的Web組件在Tomcat Web容器內運行。Web容器提供了一些服務,例如請求發送、安全、并發以及生命周期管理。它還使得Web組件可以訪問多種API, 例如命名、事務處理以及e-mail等方面的API。

          本章里描述了Web應用的組織、配置以及安裝和部署過程。第11章和第12章中講述如何開發面向服務的Web應用的Web組件。第14章和第15章講述如何開發面向表示Web的應用的Web組件。JSP技術的許多特征是由Java Servlet技術決定的,因此即使你不打算編寫servlet,也應該熟悉這方面的知識。

          大多數Web應用都使用HTTP協議,而且對HTTP的支持也正是Web組件的一個主要方面。對于HTTP協議特征的簡要總結,參見HTTP概述。

          Web應用的生命周期

          Web應用由Web組件、靜態資源文件(如圖像)、幫助類和庫組成。Java WSDP提供許多支持服務,用于增強Web組件的性能并使得它們更易于開發。不過,由于要充分考慮這些支持服務,所以Web應用在創建和運行過程上與傳統的stand-alone式的Java類有所不同。

          在Web應用被部署以后,就可以對其行為的某些方面進行配置。配置信息通過Web應用部署描述文件來維護,該文件是一種XML格式的文本文件。部署描述文件必須遵從Java Servlet規范中描述的模式。

          創建、部署和執行Web應用的過程可以總結為以下幾步:

          1.開發Web組件代碼(可能還包括部署描述文件)。

          2.建立Web應用組件連同所有靜態資源(例如圖像)和組件要引用到的幫助類。

          3.將應用安裝或部署到Web容器中。

          4.訪問指向該Web應用的URL。

          開 發Web組件代碼這方面的知識將在以后的章節中講述。接下來的幾節將對步驟2到步驟4作出詳細的講解,并給出一個Hello,World式的面向表示的應 用的例子。該應用允許用戶輸入名字到HTML表單中(見圖4-1),并且在名字提交之后顯示一條問候信息(見圖4―2)。

          Greeting Form

          圖4-1 問候表單

          Response

          圖4-2 響應

          這個Hello應用包含了兩個Web組件,用于產生問候信息和響應。在本指南中,該應用有兩個版本:一個是servlet版,名為Hello1,它的組件通過兩個servlet類(GreetingServlet.javaResponseServlet.java)來實現。另一個是JSP版,名為Hello2,它的組件通過兩個JSP頁面(greeting.jspresponse.jsp)來實現。這兩個版本的例子展示了一個包含Web組件的應用在大包、部署和運行時所涉及到的任務。如果你是在線瀏覽本指南,請務必下載本指南的捆綁包,以獲得這個示例的源代碼。

          Web應用歸檔文件

          如果要發布一個Web應用,你可以將其打包到一個Web應用歸檔文件(Web application archive,WAR)中,WAR與JAR類似,都是用作Java類庫的包。除了應用的Web組件外,Web應用的歸檔文件還包含其他的一些文件,包括:

          ·?? 服務器端的實用工具類(如數據庫bean、購物車等等)。這些類通常與JavaBeans組件的結構一致。

          ·?? 靜態Web表示內容(如HTML,圖像和聲音文件等)

          ·?? 客戶端類(applet和實用工具類)

          Web組件和靜態Web內容文件叫做Web資源

          Web應用的運行可以通過一個WAR文件,或者通過一個同為WAR格式的解包目錄。

          WAR目錄結構

          WAR的頂級目錄是該應用的文檔根目錄。這個文檔根目錄下存放著JSP頁面、客戶端類和歸檔文件,以及靜態Web資源。

          文檔根目錄下含有一個名為WEB-INF的子目錄,其中包含了以下文件和目錄:

          ·?? web.xml —— Web應用的部署描述文件。

          ·?? 標簽庫描述文件。

          ·?? classes —— 一個子目錄,包含了服務器端類:servlets,實用工具類和JavaBeans組件。

          ·?? lib —— 一個子目錄,包含了庫(標簽庫和所有作為服務器端類的實用工具類)

          還可以創建應用專用(application-specific)的子目錄(即包目錄),可以在文檔根目錄下創建,或者在WEB-INF/classes目錄下創建。

          指南示例的目錄結構

          為了便于迭代開發并且將Web應用的源代碼與已編譯的文件分開,實例的源代碼存儲在每個應用目錄mywebapp下,其結構如下:

          ·?? build.xml—— Ant生成文件

          ·?? context.xml——可選應用配置文件

          ·?? src —— servler和Javabeans組件的Java源代碼。

          ·?? web —— JSP頁面和HTML頁面、圖像。

          隨示例一起發布的Ant build文件(build.xml)中包含了一些目標 (target),用以在mywebappbuild子目錄中創建解包的WAR結構,將文件拷貝和編譯到那個目錄中,并且通過專門的Ant任務調用manager命令,來安裝、重新裝載、移除、部署和解部署應用。該指南示例的Ant目標是:

          ·?? prepare(準備) —— 創建build目錄和WAR子目錄。

          ·?? build(編譯) —— 編譯和拷貝mywebapp Web應用文件到build目錄下。

          ·?? install(安裝)—— 使用Ant install任務通知Tomcat安裝應用(見安裝Web應用)。

          ·?? reload(重新裝載)—— 使用Ant reload任務通知Tomcat重新裝載應用(見更新Web應用)。

          ·?? deploy(部署) —— 使用Ant deploy任務通知Tomcat部署應用(見部署Web應用)。

          ·?? undeploy(解除部署)——使用Ant undeploy任務通知Tomcat解除部署應用(見解除部署Web應用

          ·?? remove(移除) —— 使用 Ant remove任務通知Tomcat移除應用(見移除Web應用

          創建WAR

          手工的創建WAR文件有兩種方法:

          ·?? 使用隨J2SE SDK一起發布的JAR工具。只需簡單地在指南示例的build目錄下執行如下命令:

          jar cvf mywebapp.war .

          ·?? 使用Ant war任務

          這兩種方法都要求有創建好的Web應用部署描述文件。

          配置Web應用

          Web 應用的配置是通過包含在Web應用部署描述文件中的元素的設置來實現的。你可以使用文本編輯器來手工創建這些描述文件。接下來的章節將對你想配置的Web 應用特征作一個簡要的介紹。其中,許多的安全參數都可以在配置時指定,這些內容在第18章可以看到。如果你想得到這些特征的完整列表和描述,參見Java Servlet規范。

          在接下來的幾節中,將給出一些示例來演示Hello,World應用的配置過程。如果Hello,World沒有使用指定的配置特征,那么本節將給出其他的示例來展示部署描述文件的元素并描述指定這種特征的一般過程。



          注 意:描述符元素必須在部署描述文件中按照下列順序出現:icon,display,description,distributable,context -param,filter,filter-mapping,listener,servlet,servlet-mapping,session-config,mime-mapping,welcome-file-list,error-page,taglib,resource-env-ref,resource-ref,security-contraint,login-config,seurity-role,env-entry.


          序言

          既然部署描述文件是一種XML文檔,它就需要一個序言。Web應用的部署描述文件的序言如下所示:

          
                                
          Application 2.3//EN" "http://java.sun.com/dtd/web-
          app_2_3.dtd"> ?
          
                                
          Application 2.3//EN" "http://java.sun.com/dtd/web-
          app_2_3.dtd">? 
          ?

          別名路徑

          當Tomcat收到一個請求時,它必須決定使用哪個Web組件來處理請求。這一步是通過將包含在請求中的URL路徑映像到一個Web組件來實現的。URL路徑包含上下文根目錄(參見Installing Web Application,http://java.sun.com/webservices/docs/1.1/tutorial/doc/WebApp5.html#wp75667)和一個別名路徑。

          http://<host>:8080/context_root/alias_path 
          http://<host>:8080/context_root/alias_path 
          ?

          在servlet 可以被訪問前,Web容器必須最少有一個該組件的別名路徑。別名路徑必須以一個“/”開始,以一個字符串或者一個帶擴展名的通配符(例如:*.jsp)結 束。既然Web容器自動地映像到以*.jsp結束的別名路徑,你無需為JSP頁面指定別名路徑,除非你想通過一個名稱,而不是其文件名來引用JSP頁面。 在更新Web應用中討論的實例中,問候頁面有一個別名response.jsp,但它仍然是通過其文件名來引用的。

          在Web 部署描述文件中設置servlet版的Hello應用的映像,必須添加下列servlet和servlet-mapping元素到Web應用部署描述文件 中。為了定義JSP頁面的別名,必須替換在servlet元素中的servlet-class子元素和jsp-file子元素。

          ??greeting
          ??greeting
          ??no description
          ??GreetingServlet
          
                                
          ??response
          ??response
          ??no description
          ??ResponseServlet
          
                                
          ??greeting
          ??/greeting
          
                                
          ??response
          ??/response
           

          上下文和初始化參數

          同 一個WAR中的各Web組件共享一個表示它們的應用上下文的對象(見訪問Web上下文)。你可以傳遞參數到上下文或者Web組件。要實現這一點,你必須添 加一個context-param或init-param元素到Web應用部署描述文件中。context-param是頂級web-app元素的子元 素。init-param是servlet元素的子元素。下面的元素用于聲明一個上下文參數,該參數設置在第17章中討論的示例的資源束:

          ??
          ????
          ??????javax.servlet.jsp.jstl.fmt.localizationContext
          ????
          ????messages.BookstoreMessages
          ??
          ??...
           

          事件監聽器

          要添加事件監聽器類,必須添加一個listener元素到Web應用部署描述文件中。下面的元素描述了在第14章和第17章用到的監聽器類)。

          ??listeners.ContextListener
           

          過濾器映像

          Web 容器使用過濾器映像聲明來決定應用于某個請求的過濾器,并且決定這些過濾器的順序。正如在別名路徑中描述的那樣,該容器將請求URL與一個servlet 相匹配。要決定引用哪個過濾器,容器通過servlet名或者URL模式來匹配過濾器映像聲明。過濾器被調用的順序就是過濾器映像聲明在過濾器映像列表中 出現的順序,過濾器映像聲明將請求URI與一個servlet匹配起來。

          要指定過濾器映像,必須添加一個filter和filter-mapping元素到Web應用部署描述文件中。下面的元素用于聲明有序的過濾器,并將其映像到在第14章討論過的Receipt servlet:

          ??OrderFilter
          ??filters.OrderFilter
          
                                
          ??OrderFilter
          ??/receipt
           

          錯誤映像

          可 以指定狀態代碼與Web資源之間的映像,其中的狀態代碼可以是一個HTTP響應中返回的,也可以是由任何Web組件返回的一個Java編程語言異常中返回 的。要設置映像,必須添加一個元素到部署描述文件中。下面的元素用于將OederException映像到第14章 中使用的頁面errorpage.html。

          ??exception.OrderException
          ??/errorpage.html
           


          注意:你也可以為包含在WAR內的JSP頁面定義錯誤頁面。如果錯誤頁面是同時為WAR和JSP頁面而定義的,則JSP頁面的錯誤頁面居先。


          指向環境條目、資源環境條目或資源的引用

          如 果Web組件需要引用環境條目,資源環境條目或資源(如數據庫),必須通過在Web應用部署描述文件中的,< resource-env-ref>或元素來聲明引用。下面的元素用于聲明一個指向某個數據源的引用,該 數據源在本指南關于Web技術的幾章中要用到。

          ??jdbc/BookDB
          ??javax.sql.DataSource
          ??Container
           


          安裝Web應用

          上下文(context是映射到一個Web應用的名稱。例如,Hello1應用的上下文是/hello1。為了將應用安裝到Tomcat,需要通知Tomcat有一個新的可用上下文。

          可以使用Ant install任務來通知Tomcat有一個新的上下文。注意,在Tomcat重新啟動之后,安裝好的應用還不能使用。要永久地部署應用,參見部署Web應用。

          Ant install任務告訴由url屬性指定的在本地運行的管理器安裝一個應用,其上下文由path屬性指定,其安裝位置包含了由war屬性指定的該Web應用的文件。war屬性的值可以是一個WAR文件,如:

          jar:file:/path/to/bar.war!/ 或者是一個解包目錄:

          ?file:/path/to/foo。

          ??username="username" password="password" />

          username和password屬性將在Tomcat Web應用管理程序中討論。

          這里無需提供一個war屬性,你可以使用config屬性來指定配置信息:

          ??path="mywebapp" config="file:build/context.xml"

          ??username="username" password="password"/>

          config屬性指出一個配置文件包含上下文條目的格式

          ??docBase="../docs/tutorial/examples/web/bookstore1/build"

          ??debug="0">

          注意,這個上下文條目通過它的docBase屬性隱式地指定了Web應用文件的位置。

          本指南示例build文件包含一個Ant install target,它將調用Ant install 任務

          ??description="Install web application" depends="build">

          ??

          ????config="file:build/context.xml"

          ????username="${username}" password="${password}"/>

          Ant install任務要求Web應用部署描述文件(web.xml)是可用的。所有的指南示例應用都是隨一個部署描述文件一起發布的。

          To install the Hello1 application described in Web Application Life Cycle:

          要安裝Web應用生命周期中描述的Hello1應用,需按下列步驟:

          1. 在終端窗口中,轉到<JWSDP_HOME>/docs/tutorial/examples/web/hello1.

          2.確認Tomcat已啟動

          3.執行ant install。install target通知Tomcat新的上下文是可用的。

          部署Web應用

          如果Tomcat正在運行,就可以使用Ant deploy任務永久地將一個上下文部署到Tomcat。

          ??

          ????war="file:/path/to/mywebapp.war"

          ????username="username" password="password" />

          不同于install任務,install任務可以引用一個解包目錄,deploy任務需要一個WAR。該任務加載WAR到Tomcat并且啟動應用。也可以通過這個任務將其部署到一個遠程服務器上。

          下面是其他一些可用的部署方法,但是它們要求重新啟動Tomcat:

          ·?? 將Web應用目錄或WAR拷貝到/webapps。

          ·?? 將包含了上下文條目的名為mywebapp.xml的配置文件拷貝到/webapps。上下文條目的格式在< JWSDP_HOME>/docs/tomcat/config/context.html中的 Server Configuration Reference里有描述。注意,上下文條目通過docBase屬性隱式地指定了Web應用文件的位置。例如,下面是在第14章中討論的應用的上下文條目:

          ??

          ????docBase="../docs/tutorial/examples/web/

          ??????bookstore1/build" debug="0">

          一些實例build文件包含一個像Ant deploy 任務一樣調用的Ant deploy 目標。

          列出已安裝和部署的Web應用

          如果想列出當前在Tomcat內可使用所有Web應用,你可以使用Ant list任務:

           

          指南示例build文件包含一個像調用Ant list 任務一樣調用的Ant list 目標。

          還可以通過運行Manager Application來查看列出的應用:

          http://:8080/manager/list

          運行Web應用

          Web應用是在Web瀏覽器引用映像到組件的URL時執行的。一旦安裝了或者部署了Hello1應用,便可通過將瀏覽器指向

          http://:8080/hello1/greeting 
          來運行Web應用。

          用運行Tomcat的主機名替代。如果瀏覽器運行在與Tomcat相同的主機上,就可以用localhost替代。

          更新Web應用

          在開發期間,經常需要對Web應用進行修改。在修改servlet之后,必須:

          1.重新編譯servlet類。

          2.更新服務器上的應用。

          3.重新在客戶端裝載URL。

          更新JSP頁面時,無需重新編譯或重新裝載應用,因為Tomcat會自動完成這些事情。

          為了嘗試這一特征,修改Hello應用的servlet版本。例如,你可以將GreetingServlet返回的問候信息修改為:

          Hi, my name is Duke. What's yours?

          更新文件的過程為:

          1.?? 編輯在源碼目錄/docs/tutorial/examples/web/hello1/src中的GreetingServlet.java文件。

          2. 運行ant build任務。該任務將servlet重新編譯到build目錄中。

          更新服務器中的應用這一過程取決于你是否使用Ant install任務來安裝或者使用Ant deploy任務來部署這個應用。

          重新裝載Web應用

          如果你已經使用Ant install命令安裝了應用,就可以使用Ant reload任務來更新服務器中的應用:

          
                                
          ??username="username" password="password" /> 

          示例build文件包含一個 Ant remove目標,該目標調用 Ant remove任務。從而更新服務器中的Hello1應用,執行ant reload。為了觀察經過更新的應用,重新裝載客戶端的Hello1的URL。注意,reload任務只改變Java類,而不會改變Web.xml文件。為了重新裝載web.xml,需要將應用刪除 (參見移除Web應用)并重新安裝。

          在瀏覽器上你可以看到如圖4-3所示的屏幕:

          New Greeting

          圖4-3 新的問候信息

          為了在該實例的JSP版本上嘗試這一特性,首先建立和部署JSP版的Hello應用:

          1. 在終端窗口中,轉到

          <JWSDP_HOME>/docs/tutorial/examples/web/hello2.

          2.??? 運行ant buildbuild目標將產生所有必需的編譯并且拷貝文件到

          <JWSDP_HOME>/docs/tutorial/examples/web/hello2/build 目錄。

          3. 運行ant install。install目標將build目錄拷貝到/webappsbuild并通知Tomcat有新的應用。

          修改某一個JSP文件。然后運行ant build將經過修改的文件拷貝到docs/tutorial/examples/web/hello2/build。記住,這里無需重新裝載服務器中的應用,因為當某個JSP文件被修改時,Tomcat會自動檢測到這一情況。要查看經過修改的應用, 需重新裝載客戶端的Hello2的URL。

          重新部署Web應用

          如果已經通過使用Ant deploy任務部署了應用,就可以通過接連使用Ant undeploy任務(見解除部署Web應用)和Ant deploy任務來更新這個應用。

          移除Web應用

          如果想從服務中移除已安裝的Web應用,可以調用 Ant remove任務:

          
                                
          ??username="username" password="password" /> 

          示例build文件包含一個 Ant remove目標,該目標調用 Ant remove務。

          解除部署Web應用

          如果想移除一個已部署的Web應用,可以使用Ant undeploy任務:

          
                                
          ??username="username" password="password" /> 

          一些實例build文件包含一個Ant undeploy目標,該目標調用Ant undeploy任務

          Web應用的國際化和本地化

          所謂的國際化是指使得應用能夠支持各種語言和數據格式的過程。所謂本地化,是指使得一個國際化的應用能夠支持某種特定的或者本地的語言的過程。雖然所有客戶端用戶接口都應該被國際化和本地化,但是國際化和本地化對于Web應用來說尤其重要,因為Web本身就是無所不及的。如果想要很好地鳥瞰一下國際化與本地化問題,參見

          http://java.sun.com/docs/books/tutorial/i18n/index.html

          有兩種方法可以用于對Web應用進行國際化:

          ·?? 在每個目標位置中提供一個JSP頁面,并且使用一個控制器servlet來發送請求到適當的頁面上(取決于被請求的位置)。如果需要對一個頁面或者一個完 整的Web應用的數據進行國際化,這種方法比較有用。

          ·?? 將頁面上所有的本地敏感的數據 (例如錯誤信息,串字符或按鈕標簽) 分離到資源束內,然后訪問這些數據,來獲取響應的翻譯過來的信息并將其插入到頁面當中。這樣一來,就不是在代碼中直接創建字符串,而是創建一個包含了翻譯 過來的信息的資源束,然后使用相應的關鍵字從該資源束中讀出翻譯過來的信息。資源束可以由一個文本文件(屬性資源束)或一個包含了映像的類(列表資源束) 來支持。

          在 下面的關于Web技術的幾章中,Duke's Bookstore實例被分別國際化和本地化成英語和西班牙語。關鍵字-值對包含在名為message.BookMessage_*.class的列表資 源束。為了了解在資源束中的關鍵字-值對是怎樣的,請看在文件messages.BookMessages.java中添加的幾行:

          {"TitleCashier", "Cashier"},

          {"TitleBookDescription", "Book Description"},

          {"Visitor", "You are visitor number "},

          {"What", "What We"re Reading"},

          {"Talk", " talks about how Web components can transform the way

          you develop applications for the Web. This is a must read for

          any self respecting Web developer!"},

          {"Start", "Start Shopping"},

          為了獲得對應于某個給定用戶的正確字符串,Web組件從請求中獲取位置(由瀏覽器的語言首選項設定),為那個位置打開資源束,然后將該資源束作為會話屬性保存:

          ResourceBundle messages = (ResourceBundle)session.

          ??getAttribute("messages");

          ??if (messages == null) {

          ????Locale locale=request.getLocale();

          ????messages = ResourceBundle.getBundle("WebMessages",

          ??????locale);

          ????session.setAttribute("messages", messages);

          ??}

          Web組件從會話中獲取資源束:

          ResourceBundle messages =

          ??(ResourceBundle)session.getAttribute("messages");

          然后用下面的語句查找與關鍵字TitleCashier相關的字符串:

          messages.getString("TitleCashier");

          上面對國際化Web應用的介紹非常簡要。如果要了解更多該主題的相關信息,參見Java BluePrints:

          http://java.sun.com/blueprints

          posted @ 2005-11-09 18:01 svg_007 閱讀(286) | 評論 (0)編輯 收藏

          下一步的學習計劃

          今天確定了WEB開發的框架。確定采用XMLC+Tomcat+JavaBean的框架。從現在開始關注這方面問題!

          posted @ 2005-11-09 17:55 svg_007 閱讀(209) | 評論 (1)編輯 收藏

          JSF與Struts的異同

          Struts和JSF/Tapestry都屬于表現層框架,這兩種分屬不同性質的框架,后者是一種事件驅動型的組件模型,而Struts只是單純的MVC模式框架,老外總是急吼吼說事件驅動型就比MVC模式框架好,何以見得,我們下面進行詳細分析比較一下到底是怎么回事?

            首先事件是指從客戶端頁面(瀏覽器)由用戶操作觸發的事件,Struts使用Action來接受瀏覽器表單提交的事件,這里使用了Command模式,每個繼承Action的子類都必須實現一個方法execute。

            在struts中,實際是一個表單Form對應一個Action類(或DispatchAction),換一句話說:在Struts中實際是一 個表單只能對應一個事件,struts這種事件方式稱為application event,application event和component event相比是一種粗粒度的事件。

            struts重要的表單對象ActionForm是一種對象,它代表了一種應用,這個對象中至少包含幾個字段,這些字段是Jsp頁面表單中的 input字段,因為一個表單對應一個事件,所以,當我們需要將事件粒度細化到表單中這些字段時,也就是說,一個字段對應一個事件時,單純使用 Struts就不太可能,當然通過結合JavaScript也是可以轉彎實現的。

            而這種情況使用JSF就可以方便實現,

          <h:inputText id="userId" value="#{login.userId}">
            <f:valueChangeListener type="logindemo.UserLoginChanged" />
          </h:inputText>

            #{login.userId}表示從名為login的JavaBean的getUserId獲得的結果,這個功能使用struts也可以實現,name="login" property="userId"

            關鍵是第二行,這里表示如果userId的值改變并且確定提交后,將觸發調用類UserLoginChanged的processValueChanged(...)方法。

            JSF可以為組件提供兩種事件:Value Changed和 Action. 前者我們已經在上節見識過用處,后者就相當于struts中表單提交Action機制,它的JSF寫法如下:

          <h:commandButton id="login" commandName="login">
            <f:actionListener type=”logindemo.LoginActionListener” />
          </h:commandButton>

            從代碼可以看出,這兩種事件是通過Listerner這樣觀察者模式貼在具體組件字段上的,而Struts此類事件是原始的一種表單提交 Submit觸發機制。如果說前者比較語言化(編程語言習慣做法類似Swing編程);后者是屬于WEB化,因為它是來自Html表單,如果你起步是從 Perl/PHP開始,反而容易接受Struts這種風格。

          基本配置

            Struts和JSF都是一種框架,JSF必須需要兩種包JSF核心包、JSTL包(標簽庫),此外,JSF還將使用到Apache項目的一些commons包,這些Apache包只要部署在你的服務器中既可。

            JSF包下載地址:http://java.sun.com/j2ee/javaserverfaces/download.html選擇其中Reference Implementation。

            JSTL包下載在http://jakarta.apache.org/site/downloads/downloads_taglibs-standard.cgi

            所以,從JSF的驅動包組成看,其開源基因也占據很大的比重,JSF是一個SUN伙伴們工業標準和開源之間的一個混血兒。

            上述兩個地址下載的jar合并在一起就是JSF所需要的全部驅動包了。與Struts的驅動包一樣,這些驅動包必須位于Web項目的WEB-INF/lib,和Struts一樣的是也必須在web.xml中有如下配置:

          <web-app>
            <servlet>
              <servlet-name>Faces Servlet</servlet-name>
              <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
              <load-on-startup>1</load-on-startup>
            </servlet>

            <servlet-mapping>
              <servlet-name>Faces Servlet</servlet-name>
              <url-pattern>*.faces</url-pattern>
            </servlet-mapping>
          </web-app>

            這里和Struts的web.xml配置何其相似,簡直一模一樣。

            正如Struts的struts-config.xml一樣,JSF也有類似的faces-config.xml配置文件:


          <faces-config>
            <navigation-rule>
              <from-view-id>/index.jsp</from-view-id>
              <navigation-case>
                <from-outcome>login</from-outcome>
                <to-view-id>/welcome.jsp</to-view-id>
              </navigation-case>
            </navigation-rule>

            <managed-bean>
              <managed-bean-name>user</managed-bean-name>
              <managed-bean-class>com.corejsf.UserBean</managed-bean-class>
              <managed-bean-scope>session</managed-bean-scope>
            </managed-bean>
          </faces-config>

           

            在Struts-config.xml中有ActionForm Action以及Jsp之間的流程關系,在faces-config.xml中,也有這樣的流程,我們具體解釋一下Navigation:

            在index.jsp中有一個事件:

          <h:commandButton label="Login" action="login" />

            action的值必須匹配form-outcome值,上述Navigation配置表示:如果在index.jsp中有一個login事件,那么事件觸發后下一個頁面將是welcome.jsp

            JSF有一個獨立的事件發生和頁面導航的流程安排,這個思路比struts要非常清晰。

            managed-bean類似Struts的ActionForm,正如可以在struts-config.xml中定義ActionForm的scope一樣,這里也定義了managed-bean的scope為session。

            但是如果你只以為JSF的managed-bean就這點功能就錯了,JSF融入了新的Ioc模式/依賴性注射等技術。

          Ioc模式

            對于Userbean這樣一個managed-bean,其代碼如下:

          public class UserBean {
            private String name;
            private String password;

            // PROPERTY: name
            public String getName() { return name; }
            public void setName(String newValue) { name = newValue; }

            // PROPERTY: password
            public String getPassword() { return password; }
            public void setPassword(String newValue) { password = newValue; }
          }

          <managed-bean>
            <managed-bean-name>user</managed-bean-name>
            <managed-bean-class>com.corejsf.UserBean</managed-bean-class>
            <managed-bean-scope>session</managed-bean-scope>

            <managed-property>
              <property-name>name</property-name>
              <value>me</value>
            </managed-property>

            <managed-property>
              <property-name>password</property-name>
              <value>secret</value>
            </managed-property>
          </managed-bean>

            faces-config.xml這段配置其實是將"me"賦值給name,將secret賦值給password,這是采取Ioc模式中的Setter注射方式。

          Backing Beans

            對于一個web form,我們可以使用一個bean包含其涉及的所有組件,這個bean就稱為Backing Bean, Backing Bean的優點是:一個單個類可以封裝相關一系列功能的數據和邏輯。

            說白了,就是一個Javabean里包含其他Javabean,互相調用,屬于Facade模式或Adapter模式。


            對于一個Backing Beans來說,其中包含了幾個managed-bean,managed-bean一定是有scope的,那么這其中的幾個managed-beans如何配置它們的scope呢?

          <managed-bean>
            ...
            <managed-property>
              <property-name>visit</property-name>
              <value>#{sessionScope.visit}</value>
            </managed-property>

            這里配置了一個Backing Beans中有一個setVisit方法,將這個visit賦值為session中的visit,這樣以后在程序中我們只管訪問visit對象,從中獲取 我們希望的數據(如用戶登陸注冊信息),而visit是保存在session還是application或request只需要配置既可。

          UI界面

            JSF和Struts一樣,除了JavaBeans類之外,還有頁面表現元素,都是是使用標簽完成的,Struts也提供了struts-faces.tld標簽庫向JSF過渡。

            使用Struts標簽庫編程復雜頁面時,一個最大問題是會大量使用logic標簽,這個logic如同if語句,一旦寫起來,搞的JSP頁面象俄羅斯方塊一樣,但是使用JSF標簽就簡潔優美:

          <jia:navigatorItem name="inbox" label="InBox"
            icon="/images/inbox.gif"
            action="inbox"
            disabled="#{!authenticationBean.inboxAuthorized}"/>

            如果authenticationBean中inboxAuthorized返回是假,那么這一行標簽就不用顯示,多干凈利索!

            先寫到這里,我會繼續對JSF深入比較下去,如果研究過Jdon框架的人,可能會發現,Jdon框架的jdonframework.xml中 service配置和managed-bean一樣都使用了依賴注射,看來對Javabean的依賴注射已經迅速地成為一種新技術象征,如果你還不了解 Ioc模式,趕緊補課。

          附Jsf核心教程一個JSF案例:login.rar

          posted @ 2005-11-08 14:35 svg_007 閱讀(185) | 評論 (0)編輯 收藏

          輕量級容器的比較(Spring Framework,HiveMind,PicoContainer)(轉貼)

          輕量級容器可以動態地使系統主要組件之間的耦合變松散。不同的容器包含相同的設計模式,但卻具有根本不同的哲學。本文幫助您在下列三種輕量級容器之間作出最佳選擇:Spring Framework、HiveMind 和 PicoContainer。

          2002 年在科羅拉多的一次旅行中,我完美地感受了阿肯色河。在三段不同的漂流中,這條河展示了令人驚異的多樣性。柔美的布朗峽谷有著開闊的急流,翻滾著巨大的波 浪。Royal Gorge 別具特色的懸崖峭壁引導著巨大而筆直的峽谷之下的水力,在這條直線上發生一點小閃失都會受到長途游泳的懲罰。Numbers 具有精密的落差,需要人們在范圍狹窄的圓石花園里精確操縱。在一條河里,我有了三次極不相同的體驗。

          在我的上一篇文章“輕量級開發的成功秘訣,第 3 部分:Spring 露出水面”中,我們學習了輕量級容器的基本原理。本文將向您展示三種最流行的容器:

          • Spring Framework 具有功能齊全的容器、面向方面編程 (AOP) 模型和企業開發所需的所有集成代碼。
          • HiveMind 出自 Jakarta Tapestry 的創建者之手,它允許您為 bean 或比較大的組件(稱之為 模塊)執行依賴注入。
          • PicoContainer 是最小的輕量級容器,只支持 Java? 技術風格配置,而不支持 XML 配置。

          這三種容器都源于依賴注入,但每種容器都具有極不相同的特征。當我介紹每種容器的高級描述時,您將看到正在運行的每種框架,以及可以應用每種框架的環境。

          核心哲學

          這三種容器都接受 POJO (plain old Java object),都具有對象生命周期的鉤子(所以它們可以在創建或銷毀 bean 時調用您的代碼),都執行依賴注入。您可能認為這些主旋律將導致相似的容器,但事實并非如此。盡管植入每種容器的代碼可能相似,但容器本身反映了不同的能 力、風格和整體哲學??偠灾?,每種容器的作者都忠于他們的哲學。

          Spring Framework

          作為開放源碼框架的 Geneva,Spring Framework 為數百個 Java 2 Platform, Enterprise Edition (J2EE) API 和開放源碼框架提供了輕量級容器和膠水代碼 (glue code)。Spring 有一個最重要的前景:讓 J2EE 更易使用。讀完一些示例和書籍之后,您將看到一些常見的主題:

          • Spring 支持三種依賴注入——setter、構造函數方法 注入——但總的來說,最流行的模型是 setter 注入。
          • 在靈活性和簡單性之間,Spring 的 XML 風格配置更重視靈活性。您可以做任何事情,但對于初學者來說,配置文件是晦澀難懂的。
          • Spring 的創始人認為,容器只是整體框架的一小部分。Spring 的大部分價值來源于支持該框架的數千行膠水代碼。它易于插入任何系統中。
          • Spring 框架是三種容器實現中最完美的。一般來說,優秀的文檔都是完美編寫的。
          • Spring 具有自動連線 (autowire) 方式,但大多數示例都沒有使用它。我并不十分了解這個決策,但有時候,能夠看到明確列出的依賴關系是不錯的。
          • Spring 提供了完整的 AOP 框架,使得更容易附加服務。您可以使用 Spring 自己的框架或依賴豐富的 AspectJ 集成(參閱 參考資料)。

          如果要用一個短語來形容 Spring,我會說讓企業更強

          HiveMind

          Howard Lewis Ship 是 Jakarta Tapestry Web 框架的創建者,他還創建了 HiveMind。作為一個容器,HiveMind 是靈巧、干凈且易于使用的。與其他許多較好的開放源碼框架一樣,Ship 創建 HiveMind 是為了讓它幫助解決現實問題。但是,HiveMind 向傳統的輕量級容器添加了兩個創新:

          • 最重要的 HiveMind 創新是模塊。據 Ship 所說,Eclipse 插件激發了他的 HiveMind 模塊的靈感。
          • HiveMind 強制您編寫接口。(與所有輕量級容器一樣,它不提供接口,而由您自己提供接口。)
          • HiveMind 是用戶友好的,它提供稱為 HiveDoc 的文檔工具,友好簡明的 XML 配置,以及行準確的錯誤報告。
          • HiveMind 用戶通常優先選擇 setter 注入,但該容器還支持構造函數注入。

          如果用一個短語來形容 HiveMind 的話,我會說它是概念正確 的。

          PicoContainer

          到目前為止,PicoContainer 最重要的特征是它的尺寸。它沒有提供許多附加物,但它具有完整的依賴注入容器。PicoContainer 還具有一些惟一特性:

          • PicoContainer 很小,所以它沒有攔截器、AOP 或相似類型的服務,而選擇了讓其他框架創建這些服務。
          • PicoContainer 支持 Java 配置技術,而不支持 XML 配置技術,這與其他容器一樣。
          • PicoContainer 流行的使用模型是構造函數注入,但它也支持 setter 注入。
          • PicoContainer 沒有提供許多文檔,而且一些現有文檔是不完整的,但您不會太需要。
          • PicoContainer 具有一個自動連線方式,它很不錯。
          • PicoContainer 的發展似乎有點停滯。

          如果用一個短語來形容 PicoContainer 的話,我會選擇理論完美,但不如 Spring 或 HiveMind 實用



          回頁首


          編程模型

          現在我將向您展示社區中流行的編程示例,以幫助您更好地理解容器的作者希望您如何使用它們。我使用 PicoContainer 中的 Kiss 示例來展示 autowiring 和 Java 技術風格的配置,使用 HiveMind 加法器示例來展示模塊能力,使用 Spring PetClinic 應用程序來展示 Hibernate 集成。

          Kiss 示例 (PicoContainer)

          在這三個容器中,PicoContainer 具有最簡單的編程模型。要查看 Kiss 示例,可從 PicoContainer.org 下載它。安裝該示例,瀏覽到 docs\Two+minute+tutorial.htm,然后您會看到兩個組件:


          清單 1. 兩個 Kiss 組件

          public class Boy {
          public void kiss(Object kisser) {
          System.out.println("I was kissed by " + kisser);
          }
          }
          public class Girl {
          Boy boy;

          public Girl(Boy boy) {
          this.boy = boy;
          }

          public void kissSomeone() {
          boy.kiss(this);
          }
          }

          這兩個類是自解釋的。Girl 對 Boy 有依賴關系。該依賴關系將通過構造函數被注入。先實例化一個容器:


          MutablePicoContainer pico = new DefaultPicoContainer();

          然后注冊兩個組件:


          pico.registerComponentImplementation(Boy.class);
          pico.registerComponentImplementation(Girl.class);

          稍后您可以向 PicoContainer 請求一個對象,然后操作它:


          Girl girl = (Girl) pico.getComponentInstance(Girl.class);
          girl.kissSomeone();

          這樣就差不多了。編程模型是優雅的,基于構造函數的風格意味著您無需包括無參構造函數。對本例中的 Girl 調用這種函數將會使該對象處于不一致的狀態,因為 kiss 方法將拋出異常。

          加法器示例 (HiveMind)

          現在,讓我們看一下 HiveMind 的編程示例。從 Apache Jakarta Project 下載 HiveMind,然后查看加法器示例。您會看到接口和實現。(記?。篐iveMind 強制編寫接口。)


          清單 2. 加法器示例接口和實現

          public interface Adder
          {
          public double add(double arg0, double arg1);
          }

          public class AdderImpl implements Adder
          {
          public double add(double arg0, double arg1)
          {
          return arg0 + arg1;
          }
          }

          將該服務暴露在 XML 文件中,如下所示:


          清單 3. 將該服務暴露在 XML 文件中

          <module id="examples" version="1.0.0">

          <service-point id="Adder"
          interface="org.apache.hivemind.examples.Adder">

          <create-instance
          class="org.apache.hivemind.examples.impl.AdderImpl"/>

          </service-point>
          </module>

          然后,其他應用程序就可以使用該服務了,如下所示:


          清單 4. 其他應用程序可以使用該服務

          Registry registry = RegistryBuilder.constructDefaultRegistry();

          Adder adder = (Adder) registry.getService("examples.Adder",
          Adder.class);

          ... adder.add(arg0, arg1)

          注意,HiveMind 的模塊讓您可以將多個服務組合到一起。如果您需要向容器中的服務添加功能,可以使用攔截器:


          清單 5. 使用攔截器添加功能

          <module id="examples" version="1.0.0">
          <service-point id="Adder"
          interface="org.apache.hivemind.examples.Adder">

          <create-instance
          class="org.apache.hivemind.examples.impl.AdderImpl"/>

          <interceptor service-id="hivemind.LoggingInterceptor"/>
          </service-point>
          </module>

          PetClinic 應用程序 (Spring)

          Spring 處理事情的方法有些不同。因為 Spring 框架不帶有簡單的應用程序,我從我的書籍 Spring: A Developer's Notebook 中選擇了一個。您可以從 O'Reilly Media 獲取該示例代碼。解壓示例 4,它展示了一個用于 RentaBike 商店的帶有屬性的 CommandLineView 對象,該對象最終成為該應用程序的數據訪問對象。


          清單 6. CommandLineView 對象

          public class CommandLineView {
          private RentABike rentaBike;
          public CommandLineView() {}
          public void setRentABike(RentABike rentaBike) {this.rentaBike = rentaBike;}
          public RentABike getRentaBike() { return this.rentaBike; }
          ...
          }


          RentaBike 是具有您希望在自行車商店對象中看到的各種方法的接口:


          清單 7. 接口方法

          public interface RentABike {
          List getBikes();
          Bike getBike(String serialNo);
          void setStoreName(String name);
          String getStoreName();
          }

          沒有顯示 ArrayListBikeStore,它是 BikeStore 接口的存根實現。注意,Spring 允許編寫接口,但不強制編寫接口。下面是描述該應用程序中 bean 的 XML 配置文件:


          清單 8. 描述應用程序 bean 的 XML 配置文件

          <beans>
          <bean id="rentaBike" class="com.springbook.ArrayListRentABike">
          <property name="storeName"><value>Bruce's Bikes</value></property>
          </bean>
          <bean id="commandLineView" class="com.springbook.CommandLineView">
          <property name="rentaBike">
          <ref bean="rentaBike" />
          </property>
          </bean>
          </beans>

          該上下文中有兩個 bean。commandLineView bean 依賴于 rentaBike bean。該應用程序通過為 rentaBike 屬性指定 rentaBike 名稱,顯式解析該依賴關系。注意,PicoContainer 自動連接這種顯式關系,Spring 也可以,但大多數用戶不使用它的自動連線選項。Spring 還允許您通過攔截器或 AOP 向外觀的任何方法添加服務。



          回頁首


          比較

          既然已經看到每種容器的哲學,下面是對每種環境的無形特性的詳細比較,比如市場份額、整體質量(fit and finish)和整體特性列表。畢竟,即使編程模型是完美的,但如果沒有文檔,或者由于缺乏社區而您必須自己支持它,那么它也不會成為一個好容器。

          活動社區

          Spring 有一個充滿活力的社區,和一個支持該框架的稱為 Interface21 的職業服務公司。這很重要,因為您知道您可以獲得良好的支持,公司才有動力來支持 Spring 框架。我在社區的經歷簡直太美好了。Spring 貢獻者、創始人和用戶都以杰出的內容填滿了留言板。

          HiveMind 框架是一個 Apache Jakarta 項目,所以有著扎實的基礎。它有一個正在成長的萌芽社區。該框架的創始人 Howard Lewis Ship 是獨立顧問、優秀導師和不屈不撓的提倡者。但是,要利用 HiveMind 的質量幫助或者查找其 Web 站點之外的內容仍然十分困難。盡管如此,它的在線幫助似乎不錯,而且社區似乎正在成長。Hibernate 獲得了有趣的勝利,它被選中——或者更應該說,Ship 被選中——組成 TheServerSide.com 的新基礎設施,TheServerSide.com 是最重要的 Java 技術社區之一。

          PicoContainer 也是一個 Apache Jakarta 項目,它似乎發展緩慢。截止本文撰稿,PicoContainer 的最后一次主要代碼發行是在 2004 年 11 月。您看不到太多有關 PicoContainer 的新文章,這有點慚愧,因為我喜歡 PicoContainer 的一些哲學。事實上,我不太確定有沒有三種開放源碼輕量級容器的空間,尤其是最近第四種輕量級容器項目 Avalon 關閉之后。

          就每個社區生成的活動而言,Spring 無疑是優勝者。Interface21 的支持、奇思妙想的論壇、活躍的郵件列表以及社區的跟蹤記錄都是無與倫比的。

          整體質量

          社區的大小和實力通常驅動開放源碼項目的整體質量。充滿活力的社區需要更好的文檔和示例,而且它們會參與完成結尾的詳細信息。

          Spring 團隊編寫了可與我見過的一些比較好的商業產品相媲美的文檔。如果這還不夠的話,您還可以找到至少五本主要 Spring 書籍和其他許多包含 Spring 內容的出版物。(我自己曾撰寫過兩本有關 Spring 的書籍,其中一本書中包括 Jolt-winning Better, Faster, Lighter Java 一章,另一本是快速入門書籍 Spring: A Developer's Notebook)。錯誤消息是專業性和描述性的。與第三方框架和 API 的集成是所有 Java 技術框架中最好的。包裝是經過深思熟慮的,不過略有多余。(它幫助我開始把一些比較小的項目劃分成模塊。)示例是優秀且有指導意義的。

          與 Tapestry 一樣,HiveMind 也具有好的整體質量。Ship 自己以那些讓 HiveMind 變得簡單易用的特性而自豪,比如行準確的錯誤報告;友好簡明的 XML 語法;良好的文檔工具 HiveDoc。與用于低級詳細信息的 JavaDoc 文檔結合使用,您可以更好地描述您的應用程序(HiveMind 模塊)的高級特性,從而完善它們之間的依賴關系。

          PicoContainer 編程模型感覺自然,但文檔不完整(許多方法標記看起來過時好幾個月了),而且沒有許多使用該容器的真實世界示例。有時候,我會覺得自己在獨自穿過鬼魂出沒的破屋。

          但使用 PicoContainer 確實有一個主要優點。因為您配置現實世界的對象時,會得到一些編譯時錯誤檢查。實際上,該容器太小太輕了,以至于除了基本配置之外,沒有什么能出錯。PicoContainer 做了一項合理的工作。

          特性

          我不想過多地討論特性。如果您正在尋找許多膠水代碼來減少您的開放源碼收藏夾的集成或某特定 J2EE API,Spring 無疑是最佳選擇。HiveMind 不嘗試參與競爭。相反,它與 Spring 的服務兼容。PicoContainer 不構建而且也不嘗試構建附加物,而是選擇讓開放源碼項目為其提供服務。到目前為止,它的效果不太好。



          回頁首


          哪一個最好?

          目前,只有一個真正的答案。HiveMind 具有有趣的創新,PicoContainer 具有易于使用的模型(理論上),但社區似乎已經投票選擇了 Spring Framework。隨著時間的推移,新的容器可能會成長,HiveMind 可能不斷獲得市場份額,但目前,Spring 是您的最佳選擇。

          如果您愿意冒一些險,而使用不太成熟或不太流行的容器,您可能決定實現 HiveMind(如果需要模塊級別的配置)或 PicoContainer(如果想要微小的容器)。如果需要許多膠水代碼來集成持久引擎、事務處理策略和安全性等方面,Spring 具有最完整的組件堆。但請記?。耗梢栽?HiveMind 容器中使用 Spring 組件。

          posted @ 2005-10-23 16:46 svg_007 閱讀(961) | 評論 (0)編輯 收藏

          第一次發,試用

          這是第一次使用,試發!以后將在這里寫寫自己的學習Java的經歷和心情!

          posted @ 2005-10-10 10:37 svg_007 閱讀(132) | 評論 (0)編輯 收藏

          導航

          統計

          常用鏈接

          留言簿(2)

          隨筆檔案

          搜索

          最新評論

          • 1.?re: 下一步的學習計劃
          • 哥們,現在有多少人在用xmlc框架阿?估計沒有人用了吧。你有這方面的資料嗎?有的話給我發一份,謝謝了阿。我的郵箱abcdefghijk_a@163.com
          • --關注

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 临洮县| 确山县| 紫云| 怀仁县| 保山市| 得荣县| 北海市| 鄯善县| 皋兰县| 望都县| 巴南区| 双桥区| 绥江县| 定结县| 马公市| 宁强县| 科尔| 镇坪县| 和平区| 名山县| 竹山县| 温州市| 饶阳县| 兴文县| 德清县| 玉溪市| 焦作市| 铜川市| 泰宁县| 镇巴县| 肇州县| 乐至县| 清苑县| 东至县| 永登县| 湟源县| 香港 | 柳州市| 靖边县| 扎赉特旗| 泸州市|