用
Validator
檢查你的表單
作者:
James Holmes
用
Validator
(驗(yàn)證器)提供的豐富的內(nèi)置驗(yàn)證方法簡(jiǎn)化
Struts
的開發(fā)過(guò)程。
??????Struts
框架的一個(gè)主要好處是它提供了對(duì)接收到的表單數(shù)據(jù)進(jìn)行驗(yàn)證的內(nèi)置界面。如果有任何驗(yàn)證失敗,則應(yīng)用程序都會(huì)重新顯示
HTML
表單,這樣就可以改正無(wú)效的數(shù)據(jù)了。如果驗(yàn)證成功,則處理過(guò)程會(huì)繼續(xù)進(jìn)行。
Struts
框架的簡(jiǎn)單驗(yàn)證界面會(huì)減少與處理數(shù)據(jù)驗(yàn)證有關(guān)的令人頭疼的事情,這樣你就可以把精力集中到驗(yàn)證代碼上,而不是放到捕獲數(shù)據(jù)、重新顯示不完整或無(wú)效數(shù)據(jù)的技巧上。
但是,
Struts
內(nèi)置的驗(yàn)證界面也有缺點(diǎn)。例如,在整個(gè)應(yīng)用程序中驗(yàn)證代碼常常會(huì)大量重復(fù),因?yàn)樵S多域需要相同的驗(yàn)證邏輯。對(duì)一些相似字段的驗(yàn)證邏輯進(jìn)行任何修改都要求在幾個(gè)地方修改代碼,還要重新編譯受影響的代碼。為了解決這個(gè)問(wèn)題并增強(qiáng)
Struts
驗(yàn)證界面的功能,作為
Struts
的第三方附加件創(chuàng)建了
Validator
框架。后來(lái),
Validator
被集成到核心
Struts
代碼庫(kù)中,并從
Struts
中分離出來(lái),現(xiàn)在它是一個(gè)獨(dú)立的
Jakarta Commons
項(xiàng)目。雖然
Validator
是一個(gè)獨(dú)立的框架,但它仍能與其他程序封裝在一起后提供,并與
Struts
無(wú)縫集成。
Validator
概述
??????沒(méi)有
Validator
,你就不得不編寫驗(yàn)證表單數(shù)據(jù)所需的全部代碼,并把它放入
Form Bean
對(duì)象的
validate( )
方法中。對(duì)于想在其上進(jìn)行數(shù)據(jù)驗(yàn)證的每個(gè)
Form Bean
域來(lái)說(shuō),都需要編寫邏輯代碼來(lái)實(shí)現(xiàn)驗(yàn)證。此外,你還必須編寫代碼來(lái)存儲(chǔ)驗(yàn)證失敗時(shí)的出錯(cuò)消息。
有了
Validator
,你就不必在
Form Bean
中編寫用于驗(yàn)證或存儲(chǔ)錯(cuò)誤消息的任何代碼。相反,
Form Bean
提供了
Validator
的一個(gè)
ActionForm
子類,它提供驗(yàn)證或存儲(chǔ)錯(cuò)誤消息的功能。
可把
Validator
框架作為一個(gè)可用于
Form Bean
驗(yàn)證的可插入的驗(yàn)證例行程序系統(tǒng)來(lái)進(jìn)行安裝。每個(gè)驗(yàn)證例行程序都只是一個(gè)
Java
方法,負(fù)責(zé)執(zhí)行特定類型的驗(yàn)證任務(wù),驗(yàn)證可能通過(guò),也可能失敗。
默認(rèn)情況下,
Validator
與幾個(gè)有用的驗(yàn)證例行程序封裝在一起來(lái)提供,這些例行程序能滿足大多數(shù)情況下的驗(yàn)證要求。但是,如果
Validator
框架沒(méi)有提供你需要的驗(yàn)證例行程序,那么你可以自己創(chuàng)建定制的驗(yàn)證例行程序,并將它插入到該框架中。此外,
Validator
還支持服務(wù)器端和客戶端(
JavaScript
)的驗(yàn)證,而
Form Bean
只提供服務(wù)器端驗(yàn)證界面。
Validator
使用兩個(gè)
XML
配置文件來(lái)分別確定安裝哪個(gè)驗(yàn)證例行程序和如何將它們應(yīng)用于給定的應(yīng)用程序。第一個(gè)配置文件
validator-rules.xml
說(shuō)明應(yīng)該被插入到框架中的驗(yàn)證例行程序,并提供每個(gè)驗(yàn)證的邏輯的名稱。
validator-rules.xml
文件還定義了每個(gè)驗(yàn)證例行程序的客戶端
JavaScript
代碼。可以配置
Validator
讓它把這個(gè)
JavaScript
代碼發(fā)送到瀏覽器上,這樣驗(yàn)證就可以在客戶端和服務(wù)器端進(jìn)行了。
第二個(gè)配置文件
validation.xml
確定哪個(gè)驗(yàn)證例行程序應(yīng)用到哪個(gè)
Form Bean
。文件中的定義使用
struts-config.xml
文件給出的
Form Bean
的邏輯名稱以及
validator-rules.xml
文件給出的驗(yàn)證例行程序的邏輯名稱,以便把二者關(guān)聯(lián)起來(lái)。
使用
Validator
框架包括啟用
Validator
插件、配置
Validator
的兩個(gè)配置文件,以及創(chuàng)建提供
Validator
的
ActionForm
子類的
Form Beans
。下面詳細(xì)解釋如何配置和使用
Validator
。
啟用
Validator
插件
??????雖然
Validator
框架是與
Struts
封裝在一起提供的,但在默認(rèn)狀況下
Validator
并不被啟用。為了啟用
Validator
,要向你的應(yīng)用程序的
struts-config.xml
文件中添加下面的插件定義。
<!-- Validator Configuration -->
<plug-in className="org.apache.struts
.validator.ValidatorPlugIn">
? <set-property property="pathnames"
?????????????? value="/WEB-INF/
? validator-rules.xml, /WEB-INF/
?
? validation.xml"/>
</plug-in>
該定義告訴
Struts
為你的應(yīng)用程序加載并初始化
Validator
插件。在初始化時(shí),該插件裝入由路徑名屬性指定的、用逗號(hào)分隔的
Validator
配置文件清單。每個(gè)配置文件的路徑應(yīng)該用與
Web
應(yīng)用程序的相關(guān)的路徑來(lái)指定,如前面的例子所示。
請(qǐng)注意,你的應(yīng)用程序的
struts-config.xml
文件必須與
Struts Configuration Document Type Definition
(
Struts
配置文檔類型定義,
DTD
)一致,后者規(guī)定文件中元素出現(xiàn)的順序。所以,你必須把
Validator
插件定義放到該文件的適當(dāng)位置。確保文件中元素適當(dāng)排列的最簡(jiǎn)便方法就是使用諸如
Struts Console
的工具,它自動(dòng)格式化你的配置文件,以便與
DTD
保持一致。
配置
validator-rules.xml
??????Validator
框架可以設(shè)置為可插入系統(tǒng),其驗(yàn)證例行程序僅僅是插入到該系統(tǒng)中執(zhí)行具體驗(yàn)證的
Java
方法。
validator-rules.xml
文件說(shuō)明性地插入
Validator
用于執(zhí)行驗(yàn)證的驗(yàn)證例行程序中。
Struts
示例應(yīng)用程序帶有這個(gè)文件的預(yù)配置拷貝。在大多數(shù)情況下,你不必修改這個(gè)預(yù)配置拷貝,除非你要向該框架中添加自己定制的驗(yàn)證。
清單
1
是一個(gè)示例
validator-rules.xml
文件,說(shuō)明如何將驗(yàn)證例行程序插入到
Validator
中。
validator-rules.xml
文件中的每個(gè)驗(yàn)證例行程序都有自己的定義,它用
validator
標(biāo)記聲明,利用
name
屬性為該驗(yàn)證例行程序指定邏輯名,并指定該例行程序的類和方法。該例行程序的邏輯名稱供該文件中的其他例行程序以及
validation.xml
文件中的驗(yàn)證定義用于引用該例行程序。
請(qǐng)注意,
validator
標(biāo)記放在
javascript
的標(biāo)記中,
javascript
標(biāo)記用于定義客戶端
JavaScript
代碼,以便在客戶端執(zhí)行與服務(wù)器端相同的驗(yàn)證。
提供的驗(yàn)證程序
?????默認(rèn)情況下,
Validator
中包括幾個(gè)基本驗(yàn)證例行程序,你可以用它們來(lái)處理大多數(shù)驗(yàn)證問(wèn)題。這些例行程序具有邏輯名稱,如
required
(用于輸入要求的值)、
CreditCard
(用于輸入信用卡號(hào)碼值)、
email
(用于輸入電子郵件地址值),等等。
創(chuàng)建
Form Bean
?????為了使用
Validator
,你的應(yīng)用程序的
Form Bean
必須歸到
Validator
的
ActionForm
的某一子類,而不是
ActionForm
本身。
Validator
的
ActionForm
子類提供了
ActionForm
的
validate( )
方法(它嵌入到
Validator
框架中)的實(shí)施過(guò)程。你不必從頭編寫驗(yàn)證代碼并把它投入
validate( )
方法中,相反,可以完全忽略該方法,因?yàn)?/span>
Validator
為你提供了驗(yàn)證代碼。
與
Struts
提供的核心功能相類似,
Validator
提供給你兩種可供選擇的方法來(lái)創(chuàng)建
Form Bean
。
你可以選擇的第一種方法就是像下面這樣創(chuàng)建一個(gè)特定的
Form Bean
對(duì)象:
package com.jamesholmes.minihr;
?
import org.apache.struts.validator
.ValidatorForm;
?
?
public class LogonForm extends ValidatorForm {
? private String username;
? private String password;
?
? public String getUsername() {
??? return username;
? }
?
? public void setUsername(String
username) {
??? this.username = username;
? }
?
?
? public String getPassword() {
??? return password;
? }
public void setPassword(String
password) {
??? this.password = password;
? }
}
這個(gè)類與你不是用
Validator
所創(chuàng)建的類相似,但它提供
ValidatorForm
而不是
ActionForm
。這個(gè)類也不提供
ActionForm
的空
reset( )
和
validate( )
方法的實(shí)施過(guò)程,因?yàn)?/span>
ValidatorForm
提供了相應(yīng)過(guò)程。
在
struts-config.xml
文件中配置這個(gè)特定
Form Bean
的方法與配置正則
Form Bean
的方法相同:
<form-beans>
? <form-bean name="logonForm"
??????????? type="com.jamesholmes
? .minihr.LogonForm"/>
</form-beans>
用表單標(biāo)記的
name
屬性給特定
Form Bean
指定的邏輯名是在定義
validation.xml
文件中的驗(yàn)證時(shí)所使用的名稱,如下所示:
<!DOCTYPE form-validation
PUBLIC "-//Apache Software Foundation//
?????? DTD Commons Validator Rules
?????? Configuration 1.0//EN"
?????? "http://jakarta.apache.org/
????? commons/dtds/validator_1_0.dtd">
?
?
<form-validation>
? <formset>
??? <form name="logonForm">
????? <field property="username"
??????????? depends="required">
??????? <arg0 key="prompt.username"/>
????? </field>
??? </form>
? </formset>
</form-validation>
Validator
使用該表單標(biāo)記的
name
屬性的值將驗(yàn)證定義與要應(yīng)用這些定義的
Form Bean
的名稱相匹配。
創(chuàng)建
Form Bean
時(shí)可以選擇的第二種方法是在
struts-config.xml
文件中定義一個(gè)動(dòng)態(tài)
Form Bean
,如下所示:
<form-beans>
? <form-bean name="logonForm"
??????????? type="org.apache
.struts.validator.DynaValidatorForm">
??? <form-property name="username"
??????????? type="java.lang.String"/>
??? <form-property name="password"
??????????? type="java.lang.String"/>
? </form-bean>
</form-beans>
動(dòng)態(tài)
Form Bean
不要求創(chuàng)建特定的
Form Bean
對(duì)象;相反,要定義
Form Bean
應(yīng)該具有的屬性和類型,而
Struts
為你動(dòng)態(tài)創(chuàng)建
Form Bean
。
Validator
允許你使用這個(gè)概念,就像在核心
Struts
中使用這個(gè)概念一樣。與使用
Validator
的惟一區(qū)別就是要指定
Form Bean
是
org.apache.struts.validator.DynaValidatorForm
類型,而不是
org.apache.struts.action.DynaActionForm
類型。
分配給動(dòng)態(tài)
Form Bean
的邏輯名是在定義
validation.xml
文件中的驗(yàn)證時(shí)使用的名稱。
Validator
使用與之相匹配的名稱將這些驗(yàn)證與
Form Bean
聯(lián)系在一起。
除了創(chuàng)建
Form Bean
的這兩種標(biāo)準(zhǔn)方法之外,
Validator
還提供了一個(gè)高級(jí)特性,用于將多個(gè)驗(yàn)證定義與一個(gè)
Form Bean
定義聯(lián)系起來(lái)。當(dāng)你使用基于
validatorForm
或基于
DynaValidatorForm
的
Form Bean
時(shí),
Validator
使用
struts-config.xml
文件中的
Form Bean
的邏輯名稱,將
Form Bean
映射到
validation.xml
文件中的驗(yàn)證定義。這種機(jī)制在大多數(shù)情況下非常有用,但在某些時(shí)候,
Form Bean
要在多個(gè)操作中共享。
一個(gè)操作可能使用
Form Bean
的所有域(
fields
),而另一個(gè)操作可能只使用這些域的一個(gè)子集。因?yàn)轵?yàn)證定義被連接到
Form Bean
,所以只使用域的一個(gè)子集的操作就無(wú)法繞過(guò)對(duì)未使用域的驗(yàn)證。當(dāng)驗(yàn)證
Form Bean
時(shí),就會(huì)對(duì)未使用的域生成錯(cuò)誤消息,因?yàn)?/span>
Validator
無(wú)從知道不去驗(yàn)證未使用的域,它只是簡(jiǎn)單地把它們看作缺失或無(wú)效。
為了解決這個(gè)問(wèn)題,
Validator
提供了兩個(gè)附加的
ActionForm
子類,它使你能夠?qū)Ⅱ?yàn)證與操作相關(guān)聯(lián),而不是與
Form Bean
相關(guān)聯(lián)。這樣你就可以根據(jù)哪個(gè)操作正在使用
Form Bean
來(lái)指定把哪些驗(yàn)證用于該
Form Bean
了。對(duì)于特定的
Form Bean
,你要像下面這樣聲明
org.apache.struts.validator.ValidatorActionForm
子類:
public class AddressForm extends ValidatorActionForm {
? ...
}
對(duì)于動(dòng)態(tài)
Form Bean
,在
struts-config.xml
文件中為
Form Bean
定義指定
org.apache.struts.validator.DynaValidatorActionForm
的類型,如下所示:
<form-bean name="addressForm"
????????? type="org.apache.struts
.validator.DynaValidatorActionForm">
? ...
</form-bean>
在
validation.xml
文件中,把一組驗(yàn)證映射到一個(gè)操作路徑,而不是映射到
Form Bean
名,因?yàn)槿绻愣x了
Create Address
和
Edit Address
兩個(gè)操作(它們使用同一個(gè)
Form Bean
),那么每個(gè)操作都會(huì)有一個(gè)惟一的操作名,如下所示:
<action-mappings>
? <action path="/createAddress"
???????? type="com.jamesholmes
? .minihr.CreateAddressAction"
???????? name="addressForm"/>
? <action path="/editAddress"
???????? type="com.jamesholmes
? .minihr.EditAddressAction"
???????? name="addressForm"/>
?
</action-mappings>
下面的
validation.xml
文件片斷顯示了兩組驗(yàn)證,它們用于同一個(gè)
Form Bean
,但卻有不同的操作路徑:
<formset>
? <form name="/createAddress">
??? <field property="city"
????????? depends="required">
????? <arg0 key="prompt.city"/>
??? </field>
? </form>
? <form name="/editAddress">
??? <field property="state"
????????? depends="required">
????? <arg0 key="prompt.state"/>
??? </field>
? </form>
</formset>
因?yàn)?/span>
Form Bean
要么屬于
ValidatorActionForm
子類,要么屬于
DynaValidatorActionForm
子類,所以
Validator
知道用一個(gè)操作路徑代替
Form Bean
的邏輯名稱來(lái)找出用于
Form Bean
的驗(yàn)證。
配置
validation.xml
文件
??????validation.xml
文件用于聲明將應(yīng)用到
Form Beans
的一組驗(yàn)證。要驗(yàn)證的每個(gè)
Form Bean
在這個(gè)文件中都有自己的定義。在這個(gè)定義中,指定要應(yīng)用到該
Form Bean
的各域的驗(yàn)證。下面是一個(gè)
validation.xml
文件的例子,說(shuō)明如何定義驗(yàn)證:
<!DOCTYPE form-validation
PUBLIC "-//Apache Software Foundation//
?????? DTD Commons Validator Rules
?????? Configuration 1.0//EN"
?????? "http://jakarta.apache.org/
????? commons/dtds/validator_1_0.dtd">
?
<form-validation>
? <formset>
??? <form name="logonForm">
????? <field property="username"
??????????? depends="required">
??????? <arg0 key="prompt.username"/>
?
???
??</field>
????? <field property="password"
??????????? depends="required">
??????? <arg0 key="prompt.password"/>
????? </field>
??? </form>
? </formset>
</form-validation>
validation.xml
文件的第一個(gè)元素是
form-validation
。這個(gè)元素是該文件的主元素,而且只定義一次。在
form-validation
元素內(nèi)定義
form-set
元素,它包括多個(gè)表單元素。一般來(lái)說(shuō),在文件中只定義一個(gè)
form-set
元素,但是如果要將驗(yàn)證國(guó)際化,那就要在每個(gè)地方單獨(dú)使用一個(gè)
form-set
元素。
每個(gè)表單元素使用
name
屬性將名稱與其所包含的域驗(yàn)證集關(guān)聯(lián)起來(lái)。
Validator
使用這個(gè)邏輯名稱將這些驗(yàn)證映射到在
struts-config.xml
文件中定義的一個(gè)
Form Bean
。根據(jù)要驗(yàn)證的
Form Bean
的類型,
Validator
力求將該名稱與
Form Bean
的邏輯名稱或操作路徑相匹配。在表單元素內(nèi),
field
元素定義要應(yīng)用到
Form Bean
的特定域的驗(yàn)證。
field
元素的
property
屬性對(duì)應(yīng)于特定
Form Bean
中的域名。
depends
屬性利用
validator-rules.xml
文件指定驗(yàn)證例行程序的邏輯名稱,這些例行程序?qū)?yīng)用到域驗(yàn)證中。
配置
ApplicationResources.properties
??????Validator
使用
Struts
的資源綁定(
Resource Bundle
)機(jī)制將錯(cuò)誤消息具體化。不用在框架中對(duì)錯(cuò)誤消息進(jìn)行硬編碼,
Validator
使你能在
ApplicationResources.properties
文件中為一個(gè)消息指定一個(gè)鍵值,如果驗(yàn)證失敗則將返回該鍵值。
validator-rules.xml
文件中的每個(gè)驗(yàn)證例行程序都用
validator
標(biāo)記的
msg
屬性指定錯(cuò)誤消息的鍵值,如下所示:
<validator name="required"
????????? classname="org.apache
?
.struts.validator.FieldChecks"
????????? method="validateRequired"
????????? methodParams="java.lang
.Object, org.apache.commons.validator
.ValidatorAction, org.apache.commons
.validator.Field, org.apache.struts
.action.ActionErrors, javax.servlet
.http.HttpServletRequest"
????????? msg="errors.required">
如果在驗(yàn)證例行程序運(yùn)行時(shí)驗(yàn)證失敗,則返回與
msg
屬性指定的鍵值對(duì)應(yīng)的消息。
下面的片段顯示來(lái)自
ApplicationResources.properties
文件的驗(yàn)證出錯(cuò)時(shí)的默認(rèn)消息集,它們由
Struts
示例應(yīng)用程序提供。每個(gè)消息的鍵值對(duì)應(yīng)于每個(gè)由
validator-rules.xml
文件中的驗(yàn)證例行程序所指定的消息,它們由
Struts
示例應(yīng)用程序提供。
# Error messages for Validator framework validations
errors.required={0} is required.
errors.minlength={0} cannot be less than {1} characters.
errors.maxlength={0} cannot be greater than {2} characters.
errors.invalid={0} is invalid.
errors.byte={0} must be a byte.
errors.short={0} must be a short.
errors.integer={0} must be an integer.
errors.long={0} must be a long.0.?? errors.float={0} must be a float.
?
errors.double={0} must be a double.
errors.date={0} is not a date.
errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.
請(qǐng)注意,每條消息都有占位符,形式為
{0}
、
{1}
或
{2}
。在運(yùn)行期間,占位符被另一個(gè)值代替,如所驗(yàn)證的域的名稱。這一特性特別有用,它使你能夠創(chuàng)建可被幾個(gè)不同的域重復(fù)使用的通用驗(yàn)證錯(cuò)誤消息。
例如,下面給出
required
驗(yàn)證的錯(cuò)誤消息
errors.required
:
errors.required={0} is required.
當(dāng)你使用
validation.xml
文件中的該
required
驗(yàn)證時(shí),必須定義用于替換該錯(cuò)誤消息中的
{0}
的值,如下所示:
<form name="auctionForm">
? <field property="bid" depends="required">
??? <arg0 key="prompt.bid"/>
? </field>
</form>
錯(cuò)誤消息最多可以有
4
個(gè)占位符:
{0}
和
{3}
。這些占位符分別稱為
arg0
到
arg3
,你可以通過(guò)使用
arg0~arg3
標(biāo)記來(lái)指定它們。在上面的例子中,
arg0
標(biāo)記指定了用于替換
{0}
占位符的值。該標(biāo)記的
key
屬性指定來(lái)自
ApplicationResources.properties
文件的一個(gè)消息鍵值,它的值用于替換占位符,如下所示:
prompt.bid=Auction Bid
使用消息鍵值代替占位符的值,這一方法使你不必在
validation.xml
文件中對(duì)替換值反復(fù)硬編碼。但是,如果你不想使用
Resource Bundle
的鍵值
/
值機(jī)制來(lái)指定占位符的值,則可以使用
arg0
標(biāo)記的如下語(yǔ)法顯式地指定占位符的值:
<arg0 key="Auction Bid" resource="false"/>
在這個(gè)例子中,
resource
屬性的值設(shè)為
false
,以便通知
Validator
要把該
key
屬性指定的值作為占位符的值,而不要作為
ApplicationResources.properties
文件中消息的一個(gè)鍵值。
啟用客戶端驗(yàn)證
??????Validator
除了提供了簡(jiǎn)化服務(wù)器端表單數(shù)據(jù)驗(yàn)證過(guò)程的框架外,它還提供了執(zhí)行客戶端驗(yàn)證時(shí)易于使用的方法。在
validator-rules.xml
文件中定義的每一個(gè)驗(yàn)證例行程序都可以隨意指定
JavaScript
代碼,這些代碼可以在瀏覽器(客戶端上的)中運(yùn)行,從而執(zhí)行與服務(wù)器端進(jìn)行的驗(yàn)證相同的驗(yàn)證過(guò)程。在客戶端進(jìn)行驗(yàn)證時(shí),除非所有表單都通過(guò)驗(yàn)證,否則這些表單不允許被提交。
為了啟用客戶端驗(yàn)證,必須在每個(gè)需要驗(yàn)證的
JSP
中放上
Struts HTML Tag Library
(標(biāo)記庫(kù))的
javascript
標(biāo)記,如下所示:
<html:javascript formName="logonForm"/>
javascript
標(biāo)記要求使用
formName
屬性來(lái)為想要對(duì)其執(zhí)行驗(yàn)證的表單指定
validation.xml
文件中給出的表單定義名,如下所示:
<form name="logonForm">
? <field property="username"
??????? depends="required">
??? <arg0 key="prompt.username"/>
? </field>
? <field property="password"
??????? depends="required">
??? <arg0 key="prompt.password"/>
? </field>
</form>
為表單定義指定的服務(wù)器端的所有驗(yàn)證都將在客戶端運(yùn)行。由于客戶端驗(yàn)證用
JavaScript
執(zhí)行,所以可以有多種方法不去執(zhí)行它。要確保驗(yàn)證過(guò)程總是能運(yùn)行,不論你是否選擇啟用了客戶端驗(yàn)證,
Validator
都在服務(wù)器端執(zhí)行這些驗(yàn)證。
結(jié)論
??????Validator
框架針對(duì)表單數(shù)據(jù)的驗(yàn)證提供了可配置的系統(tǒng),從而為核心
Struts
框架添加了很多有價(jià)值的功能。通過(guò)把
Validator
框架用于你的應(yīng)用程序,你可以節(jié)約時(shí)間并簡(jiǎn)化
Struts
應(yīng)用程序的開發(fā)過(guò)程。