(1)
1. 介紹
1.1 Model-View-Controller (MVC) 設(shè)計(jì)模式
FIXME - 需要一個(gè)對該模式一般性的介紹。(譯注:可以參考機(jī)械工業(yè)出版社的《設(shè)計(jì)模式》。)
1.2 將MVC概念映射到Struts組件中
Struts 的體系結(jié)構(gòu)實(shí)現(xiàn)了Model-View-Controller設(shè)計(jì)模式的概念,它將這些概念映射到web應(yīng)用程序的組件和概念中?!?
這一體系結(jié)構(gòu)中每個(gè)主要的組件都將在下面做詳細(xì)的討論?!?
1.3 Model: 系統(tǒng)狀態(tài)和商業(yè)邏輯JavaBeans
基于MVC的系統(tǒng)中的 Model 部分可以細(xì)分為兩個(gè)概念 -- 系統(tǒng)的內(nèi)部狀態(tài), 能夠改變狀態(tài)的行為。用語法術(shù)語來說,我們可以把狀態(tài)信息當(dāng)作名詞(事物),把行為當(dāng)作動(dòng)詞(事物狀態(tài)的改變)?!?
通常說來,你的應(yīng)用程序?qū)⑾到y(tǒng)內(nèi)部的狀態(tài)表示為一組一個(gè)或多個(gè)的JavaBeans,使用屬性(properties)來表示狀態(tài)的細(xì)節(jié)。依賴于你的應(yīng)用程序的復(fù)雜度,這些beans可以是自包含的(以某種方式知道怎樣永久地保存它們的狀態(tài)信息),或者可以是正面的(facades),知道當(dāng)被請求時(shí)怎樣從外部數(shù)據(jù)源(例如數(shù)據(jù)庫)中取得信息。Entity EJBs通常也用來表示內(nèi)部狀態(tài)。
大型應(yīng)用程序經(jīng)常將系統(tǒng)可能的商業(yè)邏輯行為表示為可以被維護(hù)狀態(tài)信息的beans調(diào)用的方法。舉個(gè)例子,你有一個(gè)為每個(gè)當(dāng)前用戶保存在session中的購物車bean,里面是表示當(dāng)前用戶決定購買物品的屬性。這個(gè)bean有一個(gè)checkOut()方法用來驗(yàn)證用戶的信用卡,將定單發(fā)給庫房以選擇貨品和出貨。別的系統(tǒng)分別地表示同樣的行為,或許使用Session EJBs。
在一些小型應(yīng)用程序中,同樣的行為又可能嵌入到作為Controller一部分的 Action 類中。這在邏輯非常簡單或者并不想要在其它環(huán)境中重用這些商業(yè)邏輯時(shí)是恰當(dāng)?shù)?。Struts框架支持所有這些方法,但建議將商業(yè)邏輯(“做什么”)和 Action 類(“決定做什么”)分離開。
1.4 View: JSP頁面和表示組件
基于Struts的應(yīng)用程序中的 View 部分通常使用JSP技術(shù)來構(gòu)建。JSP頁面包含稱為“模版文本”的靜態(tài)HTML(或XML)文本,加上插入的基于對特殊行為標(biāo)記解釋的動(dòng)態(tài)內(nèi)容。JSP環(huán)境包括了其用途由JSP規(guī)范來描述的一套標(biāo)準(zhǔn)的行為標(biāo)記,例如
Struts包括了一個(gè)廣闊的便于創(chuàng)建用戶界面,并且充分國際化的定制標(biāo)記庫,與作為系統(tǒng) Model 部分一部分的ActionForm beans美妙地相互配合。這些標(biāo)記的使用將在后面做詳細(xì)討論。
除了JSP頁面和其包含的行為及定制標(biāo)記,商業(yè)對象經(jīng)常需要能夠基于它們在被請求時(shí)的當(dāng)前狀態(tài)將自己處理成HTML(或XML)。從這些對象處理過的輸出可以很容易地使用
1.5 Controller: ActionServlet和ActionMapping
應(yīng)用程序的 Controller 部分集中于從客戶端接收請求(典型情況下是一個(gè)運(yùn)行瀏覽器的用戶),決定執(zhí)行什么商業(yè)邏輯功能,然后將產(chǎn)生下一步用戶界面的責(zé)任委派給一個(gè)適當(dāng)?shù)腣iew組件。在Struts中,controller的基本組件是一個(gè) ActionServlet 類的servlet。這個(gè)servlet通過定義一組映射(由Java接口 ActionMapping 描述)來配置。每個(gè)映射定義一個(gè)與所請求的URI相匹配的路徑和一個(gè) Action 類(一個(gè)實(shí)現(xiàn) Action 接口的類)完整的類名,這個(gè)類負(fù)責(zé)執(zhí)行預(yù)期的商業(yè)邏輯,然后將控制分派給適當(dāng)?shù)腣iew組件來創(chuàng)建響應(yīng)?!?
Struts也支持使用包含有運(yùn)行框架所必需的標(biāo)準(zhǔn)屬性之外的附加屬性的 ActionMapping 類的能力。這允許你保存特定于你的應(yīng)用程序的附加信息,同時(shí)仍可利用框架其余的特性。另外,Struts允許你定義控制將重定向到的邏輯名,這樣一個(gè)行為方法可以請求“主菜單”頁面(舉例),而不需要知道相應(yīng)的JSP頁面的實(shí)際名字是什么。這個(gè)功能極大地幫助你分離控制邏輯(下一步做什么)和顯示邏輯(相應(yīng)的頁面的名稱是什么)?!?
2. 創(chuàng)建Model組件
2.1 概述
你用到的應(yīng)用程序的需求文檔很可能集中于創(chuàng)建用戶界面。然而你應(yīng)該保證每個(gè)提交的請求所需要的處理也要被清楚的定義。通常說來,Model 組件的開發(fā)者集中于創(chuàng)建支持所有功能需求的JavaBeans類。一個(gè)特殊應(yīng)用要求的beans的精確特性依賴于具體需求變化會(huì)非常的大,但是它們通??梢苑殖上旅嬗懻摰膸追N類型。然而,首先對“范圍”概念做一個(gè)簡短的回顧是有用的,因?yàn)樗cbeans有關(guān)。
2.2 JavaBeans和范圍
在一個(gè)基于web的應(yīng)用程序中,JavaBeans可以被保存在(并從中訪問)一些不同“屬性”的集合中。每一個(gè)集合都有集合生存期和所保存的beans可見度的不同的規(guī)則??偟恼f來,定義生存期和可見度的這些規(guī)則被叫做這些beans的 范圍 。JSP規(guī)范中使用以下術(shù)語定義可選的范圍(在圓括號中定義servlet API中的等價(jià)物):
page - 在一個(gè)單獨(dú)的JSP頁面中可見的Beans,生存期限于當(dāng)前請求。(service()方法中的局部變量) request - 在一個(gè)單獨(dú)的JSP頁面中可見的Beans,也包括所有包含于這個(gè)頁面或從這個(gè)頁面重定向到的頁面或servlet。(Request屬性)
session - 參與一個(gè)特定的用戶session的所有的JSP和servlet都可見的Beans,跨越一個(gè)或多個(gè)請求。(Session屬性)
application - 一個(gè)web應(yīng)用程序的所有JSP頁面和servlet都可見的Beans。(Servlet context屬性)
記住同一個(gè)web應(yīng)用程序的JSP頁面和servlets共享同樣一組bean集合是很重要的。例如,一個(gè)bean作為一個(gè)request屬性保存在一個(gè)servlet中,就象這樣:
MyCart mycart = new MyCart(...);
request.setAttribute("cart", mycart);
將立即被這個(gè)servlet重定向到的一個(gè)JSP頁面使用一個(gè)標(biāo)準(zhǔn)的行為標(biāo)記看到,就象這樣:
2.3 ActionForm Beans
Struts框架通常假定你已經(jīng)為每一個(gè)你的應(yīng)用程序中請求的輸入創(chuàng)建了一個(gè) ActionForm bean(即一個(gè)實(shí)現(xiàn)了 ActionForm 接口的類)。如果你在你的 ActionMapping 配置文件中定義了這樣的beans(見“創(chuàng)建Controller組件”),Struts的controller servlet在調(diào)用適當(dāng)?shù)摹ction 方法前將自動(dòng)為你執(zhí)行如下的服務(wù):
用適當(dāng)?shù)年P(guān)鍵字檢查用戶的session中是否有適當(dāng)?shù)念惖腷ean的一個(gè)實(shí)例?!?
如果沒有這樣的session范圍的bean,自動(dòng)建立一個(gè)新的bean并添加到用戶的session中?!?
對每個(gè)名字對應(yīng)于bean中的一個(gè)屬性的請求參數(shù),調(diào)用相應(yīng)的set方法。這個(gè)操作類似于當(dāng)你以通配符“*”選擇所有屬性使用標(biāo)準(zhǔn)的JSP行為標(biāo)記
更新的ActionForm bean在被調(diào)用時(shí)將被傳遞給Acton類的perform()方法,以使這些值能夠立即生效?!?
當(dāng)你在寫你的ActionForm beans時(shí),記住以下的原則:
ActionForm 接口本身不需要特殊的實(shí)現(xiàn)方法。它是用來標(biāo)識(shí)這些特定的beans在整個(gè)體系結(jié)構(gòu)中的作用。典型情況下,一個(gè)ActionForm bean只包括屬性的get方法和set方法,沒有商業(yè)邏輯?!?
通常在一個(gè)ActionForm bean中只有很少的輸入驗(yàn)證邏輯。這樣的beans存在的主要理由是保存用戶為相關(guān)的表單所輸入的大部分近期值 -- 甚至在錯(cuò)誤被檢測到時(shí) -- 這樣同樣的頁面可以被重建,伴隨有一組出錯(cuò)信息,這樣用戶僅僅需要糾正錯(cuò)誤的字段。用戶輸入的驗(yàn)證應(yīng)該在 Action 類中執(zhí)行(如果是很簡單的話),或者在適當(dāng)?shù)纳虡I(yè)邏輯beans中執(zhí)行。
為每個(gè)表單中出現(xiàn)的字段定義一個(gè)屬性(用相關(guān)的getXxx()和setXxx()方法)。字段名和屬性名必須按照J(rèn)avaBeans的約定相匹配。例如,一個(gè)名為 username 的輸入字段將引起 setUsername() 方法被調(diào)用?!?
你應(yīng)該注意一個(gè)“表單”在這里討論時(shí)的意義并不必須對應(yīng)于用戶界面中的一個(gè)單獨(dú)的JSP頁面。在很多應(yīng)用程序中一個(gè)“表單”(從用戶的觀點(diǎn))延伸至多個(gè)頁面也是很平常的。想想看,例如,通常在安裝新的應(yīng)用程序時(shí)使用的導(dǎo)航安裝程序的用戶界面。Struts鼓勵(lì)你定義一個(gè)包含所有字段屬性的單獨(dú)的ActionForm bean。不管字段實(shí)際上是顯示在哪個(gè)頁面上。同樣的,同一表單的不同的頁面應(yīng)該提交到相同的Action類。如果你遵照這個(gè)建議,在大多數(shù)情況下,頁面設(shè)計(jì)者可以重新組織不同頁面中的字段而不需要改變處理邏輯?!?
2.4 系統(tǒng)狀態(tài)Beans
系統(tǒng)的實(shí)際狀態(tài)通常表示為一組一個(gè)或多個(gè)的JavaBeans類,其屬性定義當(dāng)前狀態(tài)。例如,一個(gè)購物車系統(tǒng)包括一個(gè)表示購物車的bean,這個(gè)bean為每個(gè)單獨(dú)的購物者維護(hù),這個(gè)bean中包括(在其它事物之中)一組購物者當(dāng)前選擇購買的項(xiàng)目。分別地,系統(tǒng)也包括保存用戶信息(包括他們的信用卡和送貨地址)、可獲得項(xiàng)目的目錄和它們當(dāng)前庫存水平的不同的beans。
對于小規(guī)模的系統(tǒng),或者對于不需要長時(shí)間保存的狀態(tài)信息,一組系統(tǒng)狀態(tài)beans可以包含所有系統(tǒng)曾經(jīng)經(jīng)歷的特定細(xì)節(jié)的信息?;蛘呓?jīng)常是,系統(tǒng)狀態(tài)beans表示永久保存在一些外部數(shù)據(jù)庫中的信息(例如CustomerBean對象對應(yīng)于表 CUSTOMERS 中的特定的一行),在需要時(shí)從服務(wù)器的內(nèi)存中創(chuàng)建或清除。在大規(guī)模應(yīng)用程序中,Entity EJBs也用于這種用途?!?
2.5 商業(yè)邏輯Beans
你應(yīng)該把你的應(yīng)用程序中的功能邏輯封裝成對為此目的設(shè)計(jì)的JavaBeans的方法調(diào)用。這些方法可以是用于系統(tǒng)狀態(tài)beans的相同的類的一部分,或者可以是在專門執(zhí)行商業(yè)邏輯的獨(dú)立的類中。在后一種情況下,你通常需要將系統(tǒng)狀態(tài)beans傳遞給這些方法作為參數(shù)處理?!?
為了代碼最大的可重用性,商業(yè)邏輯beans應(yīng)該被設(shè)計(jì)和實(shí)現(xiàn)為它們不知道自己被執(zhí)行于web應(yīng)用環(huán)境中。如果你發(fā)現(xiàn)在你的bean中你必須import一個(gè) javax.servlet.* 類,你就把這個(gè)商業(yè)邏輯捆綁在了web應(yīng)用環(huán)境中??紤]重新組織事物使你的 Action 類(Controller任務(wù)的一部分,在下面描述)翻譯所有從HTTP請求中請求被處理為對你的商業(yè)邏輯beans屬性set方法調(diào)用的信息,然后可以發(fā)出一個(gè)對 execute() 的調(diào)用。這樣的一個(gè)商業(yè)邏輯類可以被重用在除它們最初被構(gòu)造的web應(yīng)用程序以外的環(huán)境中?!?
依賴于你的應(yīng)用程序的復(fù)雜度和范圍,商業(yè)邏輯beans可以是與作為參數(shù)傳遞的系統(tǒng)狀態(tài)beans交互作用的普通的JavaBeans,或者使用JDBC調(diào)用訪問數(shù)據(jù)庫的普通的JavaBeans。而對于較大的應(yīng)用程序,這些beans經(jīng)常是有狀態(tài)或無狀態(tài)的EJBs?!?
2.6 題外話: 訪問關(guān)系數(shù)據(jù)庫
很多web應(yīng)用程序利用一個(gè)關(guān)系數(shù)據(jù)庫(通過一個(gè)JDBC driver訪問)來保存應(yīng)用程序相關(guān)的永久數(shù)據(jù)。其它應(yīng)用程序則使用Entity EJBs來實(shí)現(xiàn)這個(gè)目的,他們委派EJBs自己來決定怎樣維護(hù)永久狀態(tài)。如果你是使用EJBs來實(shí)現(xiàn)這個(gè)目的,遵照EJB規(guī)范中描述的客戶端設(shè)計(jì)模式?!?
對于基于直接數(shù)據(jù)庫訪問的web應(yīng)用程序,一個(gè)普通的設(shè)計(jì)問題是當(dāng)需要訪問低層數(shù)據(jù)庫時(shí)怎樣產(chǎn)生一個(gè)適當(dāng)?shù)腏DBC連接對象。解決這個(gè)問題有幾種方法 -- 以下原則描述了推薦的一種方法:
創(chuàng)建或得到一個(gè)允許一組數(shù)據(jù)庫連接被多個(gè)用戶共享的ConnectionPool類。Struts(當(dāng)前)沒有包括這樣的一個(gè)類,但是有很多這樣的類可以得到。
當(dāng)應(yīng)用程序初始化時(shí),在應(yīng)用程序展開(deployment)描述符中定義一個(gè)有一個(gè)“啟動(dòng)時(shí)加載”值的servlet。我們將把這個(gè)servlet叫做 啟動(dòng) servlet。在大多數(shù)情況下,這個(gè)servlet不需要處理任何的請求,所以沒有一個(gè)
在啟動(dòng)servlet的 init() 方法中,配置并初始化一個(gè)ConnectionPool類的實(shí)例,將其保存為一個(gè)servlet context屬性(從JSP的觀點(diǎn)看等同于一個(gè)application范圍的bean)。通?;趥鬟f給啟動(dòng)servlet初始化參數(shù)來配置聯(lián)接緩沖池是很方便的?!?
在啟動(dòng)servlet的 destroy() 方法中,包含了釋放聯(lián)接緩沖池所打開的聯(lián)接的邏輯。這個(gè)方法將在servlet容器結(jié)束這個(gè)應(yīng)用程序的時(shí)候被調(diào)用?!?
當(dāng) Action 類需要調(diào)用一個(gè)需要數(shù)據(jù)庫聯(lián)接的商業(yè)邏輯bean中的方法(例如“insert a new customer”)時(shí),將執(zhí)行下面的步驟:
為這個(gè)web應(yīng)用程序從servelt context屬性中得到一個(gè)聯(lián)接緩沖池對象。
調(diào)用聯(lián)接緩沖池對象的 open() 方法來得到一個(gè)在 Action 類調(diào)用中使用的聯(lián)接?!?
調(diào)用商業(yè)邏輯bean中合適的方法,將數(shù)據(jù)庫聯(lián)接對象作為一個(gè)參數(shù)傳遞給它?!?
調(diào)用分配的聯(lián)接中的 close() 方法,這將引起這個(gè)聯(lián)接為了以后其它請求的重用被返回到緩沖池中。
一個(gè)通常的編程錯(cuò)誤是忘記了把數(shù)據(jù)庫聯(lián)接返回給緩沖池,這將最終導(dǎo)致用完所有的聯(lián)接。一定要確信 Action 類的邏輯總是返回聯(lián)接,甚至在商業(yè)邏輯bean拋出一個(gè)違例時(shí)。
遵照上面推薦的設(shè)計(jì)模式意味著你能夠編寫你的商業(yè)邏輯類而不需要擔(dān)心它們怎樣得到一個(gè)JDBC聯(lián)接來使用-- 簡單地在任何需要訪問數(shù)據(jù)庫的方法中包含一個(gè)Connection參數(shù)。當(dāng)你的商業(yè)邏輯類在一個(gè)web應(yīng)用程序中被利用時(shí),分配和釋放適當(dāng)?shù)穆?lián)接是 Action 類的責(zé)任。當(dāng)你使用相同的商業(yè)邏輯類時(shí),例如,在一個(gè)批處理工作中,提供一個(gè)適當(dāng)?shù)穆?lián)接是那個(gè)應(yīng)用程序的責(zé)任(這不需要從緩沖池中獲得,因?yàn)榇蠖鄶?shù)批處理工作運(yùn)行于一個(gè)單線程環(huán)境中)?!?
3. 創(chuàng)建View組件
3.1 概述
這一章集中于創(chuàng)建應(yīng)用程序中的 View 組件的任務(wù),主要使用JSP技術(shù)建立。特別的,Struts除了提供了與輸入表單的交互外還提供了建立國際化應(yīng)用程序的支持。幾個(gè)其它的與View相關(guān)的主題也被簡單地討論?!?
3.2 國際化消息
幾年之前,應(yīng)用程序開發(fā)者能夠考慮到僅僅支持他們本國的只使用一種語言(或者有時(shí)候是兩種)和通常只有一種數(shù)量表現(xiàn)方式(例如日期、數(shù)字、貨幣值)的居民。然而,基于web技術(shù)的應(yīng)用程序的爆炸性增長,以及將這些應(yīng)用程序展開在Internet或其它被廣泛訪問的網(wǎng)絡(luò)之上,已經(jīng)在很多情況下使得國家的邊界淡化到不可見。這種情況轉(zhuǎn)變成為一種對于應(yīng)用程序支持國際化(經(jīng)常被稱做“i18n”,因?yàn)?8是字母“i”和字母“n”之間的字母個(gè)數(shù))和本地化的需求?!?
Struts建立于Java平臺(tái)之上為建立國際化和本地化的應(yīng)用程序提供幫助。需要熟悉的關(guān)鍵概念是:
Locale - 基礎(chǔ)的支持國際化的Java類是 java.util.Locale 。每個(gè) Locale 代表一個(gè)特別的國家和語言選擇(加上一個(gè)可選的語言變量),以及一套格式假定,例如數(shù)字和日期等等。
ResourceBundle - java.util.ResourceBundle 類提供支持多種語言消息的基本工具。查看文檔中關(guān)于ResourceBundle 類以及你的JDK版本的文檔包中關(guān)于國際化的更多內(nèi)容?!?
PropertyResourceBundle - 一個(gè) ResourceBundle 類的標(biāo)準(zhǔn)實(shí)現(xiàn)允許你使用與初始化properties文件同樣的“name=value”語法來定義資源。這對于使用為用于一個(gè)web應(yīng)用程序的消息準(zhǔn)備資源包是非常方便的,因?yàn)檫@些消息通常都是面向文本的?!?
MessageFormat - java.text.MessageFormat 類允許你使用運(yùn)行時(shí)指定的參數(shù)替換一個(gè)消息字符串中的一部分(在這種情況下,是一個(gè)從一個(gè)資源包得到的消息)。這在你創(chuàng)建一個(gè)句子的場合中是有用的,但是詞會(huì)以不同的語言按照不同的順序出現(xiàn)。消息中的占位符字符串{0}用第一個(gè)運(yùn)行時(shí)參數(shù)替換,{1}用第二個(gè)運(yùn)行時(shí)參數(shù)替換,以此類推?!?
MessageResources - Struts的類 org.apache.struts.util.MessageResources 使你能夠?qū)⒁惶踪Y源包視做一個(gè)數(shù)據(jù)庫,并且允許你為一個(gè)特定的Locale(通常是與當(dāng)前用戶相對應(yīng))請求一個(gè)特定的消息,而不是為服務(wù)器運(yùn)行在其中的缺省的Locale請求消息?!?
對于一個(gè)國際化的應(yīng)用程序,遵照J(rèn)DK文檔包中國際化文檔所描述的步驟來創(chuàng)建一個(gè)包含每種語言的消息的屬性文件。下面舉一個(gè)例子說明?!?
假設(shè)你的源代碼建立在包 com.mycompany.mypackage 中,因此它保存于一個(gè)叫做(相對于你的源目錄)com/mycompany/mypackage 的目錄中。為創(chuàng)建一個(gè)叫做 com.mycompany.mypackage.MyResources 的資源包,你應(yīng)該在目錄 com/mycompany/mypackage 中創(chuàng)建下列文件:
MyResources.properties - 包含你的服務(wù)器的缺省語言的消息。如果你的缺省語言是英語,你可能有一個(gè)這樣的條目:
prompt.hello=Hello
MyResources_xx.properties - 包含ISO語言編程為“xx”(查看ResourceBundle的Java文檔頁面得到一個(gè)當(dāng)前列表的聯(lián)接)的同樣的消息。對于上面的消息的法語版,你可以有這個(gè)條目:
prompt.hello=Bonjour
你可以有你需要的任意多的語言的資源包文件。
當(dāng)你在web應(yīng)用程序展開描述符中配置controller servlet時(shí),你需要在一個(gè)初始化參數(shù)中定義的一件事是應(yīng)用程序的資源包的基礎(chǔ)名。在上述的情況中,這應(yīng)該是 com.mycompany.mypackage.MyResources ?!?
3.3 表單和FormBean的交互
大部分web開發(fā)者曾經(jīng)使用HTML的標(biāo)準(zhǔn)性能來建立表單,例如使用 標(biāo)記。用戶希望交互程序具有一定的行為,這些期待中的一個(gè)與錯(cuò)誤處理有關(guān) -- 如果用戶出現(xiàn)一個(gè)錯(cuò)誤,應(yīng)用程序應(yīng)該允許他們僅僅修改需要修改的部分 -- 而不需要重新敲入當(dāng)前頁面或表單中的任何其它信息?!?
使用標(biāo)準(zhǔn)的HTML和JSP編程來完全實(shí)現(xiàn)這個(gè)期望是單調(diào)而繁重的。舉例來說,一個(gè)用戶名字段的輸入元素看起來可以象是這樣(在JSP中)
value="<%= loginBean.getUsername() %>">
這很難敲對,會(huì)把沒有編程概念的HTML開發(fā)者搞糊涂,并且會(huì)在HTML編輯器中造成問題。取而代之的是,Struts提供了一種全面的基于JSP 1.1的定制標(biāo)記庫功能的機(jī)制來建立表單。上面的情況使用Struts處理后將象是這樣:
沒有必要再顯式地涉及到從中獲得初始值的JavaBean。這將由框架自動(dòng)處理?!?
3.3.1 使用Struts建立表單
一個(gè)完整的注冊表單將演示Struts相對于直接使用HTML和標(biāo)準(zhǔn)的JSP功能怎樣極大地減輕了處理表單的痛苦??紤]以下稱為logon.jsp的頁面(來自Struts的例子程序):
<%@ page language="java" %>
<%@ taglib uri="/WEB-INF/struts.tld" prefix="struts" %>
| |
---|---|
| |
| |
下面的條目基于這個(gè)例子演示在Struts中處理表單的關(guān)鍵的特性:
taglib指令告訴JSP頁面編譯器從哪里找到Struts標(biāo)記庫的 標(biāo)記庫描述符 。在這種情況下,我們使用struts作為前綴來標(biāo)識(shí)來自這個(gè)庫中的標(biāo)記,但是可以使用任何你想用的前綴?!?
這個(gè)頁面使用了幾個(gè) message 標(biāo)記來從一個(gè)包含有這個(gè)應(yīng)用程序所有資源的 MessageResources 對象中查找國際化的消息字符串。為了讓這個(gè)頁面能夠工作,以下的消息關(guān)鍵字必須在這些資源中被定義:
logon.title - 注冊頁面的標(biāo)題
prompt.username - 一個(gè) “Username:” 提示字符串
prompt.password - 一個(gè) “Password:” 提示字符串
button.submit - “Submit”按鈕的標(biāo)簽
button.reset - “Reset”按鈕的標(biāo)簽
當(dāng)用戶注冊時(shí),應(yīng)用程序可以在用戶的session中保存一個(gè) Locale 對象。這個(gè) Locale 將用來選擇適當(dāng)語言的消息。這使得給用戶一個(gè)切換語言的可選項(xiàng)實(shí)現(xiàn)起來變的容易了 -- 僅僅改變保存的 Locale 對象,所有的消息就會(huì)自動(dòng)切換?!?
errors 標(biāo)記顯示由一個(gè)商業(yè)邏輯組件保存的任何出錯(cuò)消息,或者如果沒有出錯(cuò)消息保存就什么都沒有。這個(gè)標(biāo)記將在下面做深入的描述?!?
form 標(biāo)記基于指定的屬性對一個(gè)HTML