只要你使用了Struts一段時間,你就會開始注意到你花了很多時間來創建ActionForm 類。盡管這些類對于Struts的MVC結構很重要(因為他們實現了視圖部分),但他們通常只是bean屬性和 validate 方法(有時也稱為reset 方法)的匯集。有了Struts 1.1版本,開發者就有了一組新的選項來創建他們的視圖對象,在DynaBeans的基礎上創建。DynaBeans是動態配置的Java Beans,這就意味著:他們可從外部配置(通常為XML)的某些種類中獲取他們的屬性,而不是通過在類中明確定義的方法處獲得。
為了說明DynaBeans (和Struts實現,Dynaforms)的工作原理,我們首先討論一個簡單的 Struts Form ,它主要記錄姓名、地址、和電話號碼。下面就是如何使用ActionForm 來實現它的過程。
article1.CustomerForm
package article1;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionError;
import javax.servlet.http.HttpServletRequest;
public class CustomerForm extends ActionForm {
protected boolean nullOrBlank (String str) {
return ((str == null) || (str.length() == 0));
}
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if (nullOrBlank(lastName)) {
errors.add("lastName",
new ActionError("article1.lastName.missing"));
}
if (nullOrBlank(firstName)) {
errors.add("firstName",
new ActionError("article1.firstName.missing"));
}
if (nullOrBlank(street)) {
errors.add("street",
new ActionError("article1.street.missing"));
}
if (nullOrBlank(city)) {
errors.add("city",
new ActionError("article1.city.missing"));
}
if (nullOrBlank(state)) {
errors.add("state",
new ActionError("article1.state.missing"));
}
if (nullOrBlank(postalCode)) {
errors.add("postalCode",
new ActionError("article1.postalCode.missing"));
}
if (nullOrBlank(phone)) {
errors.add("phone",
new ActionError("article1.phone.missing"));
}
return errors;
}
private String lastName;
private String firstName;
private String street;
private String city;
private String state;
private String postalCode;
private String phone;
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
} |
如你所見,這是一個帶有有效方法的標準JavaBean,它保證所有的域都正確設置。
與這個bean接口的JSP 頁也同樣簡單:
customer.jsp
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<%@ taglib prefix="fmt" uri="/WEB-INF/fmt.tld" %>
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<head>
<title>Example of a standard Customer form</title>
</head>
<h1>Example of a standard Customer form</h1>
<html:form action="/addCustomer">
Last Name: <html:text property="lastName"/>
<html:errors property="lastName" /><br>
First Name: <html:text property="firstName"/>
<html:errors property="firstName" /><br>
Street Addr: <html:text property="street"/>
<html:errors property="street" /><br>
City: <html:text property="city"/>
<html:errors property="city" /><br>
State: <html:text property="state" maxlength="2" size="2" />
<html:errors property="state" /><br>
Postal Code: <html:text property="postalCode" maxlength="5"
size="5" />
<html:errors property="postalCode" /><br>
Telephone: <html:text property="phone" maxlength="11" size="11" />
<html:errors property="phone" /><br>
<html:submit/>
</html:form> |
用于該頁的Action只發送值到標準輸出(它會將值放在 Catalina 日志文件內):
article1.AddCustomerAction
package article1;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionForm;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
public class AddCustomerAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException{
CustomerForm custForm = (CustomerForm) form;
System.out.println("lastName = "
+ custForm.getLastName());
System.out.println("firstName = "
+ custForm.getFirstName());
System.out.println("street = " + custForm.getStreet());
System.out.println("city = " + custForm.getCity());
System.out.println("state = " + custForm.getState());
System.out.println("postalCode = "
+ custForm.getPostalCode());
System.out.println("phone = " + custForm.getPhone());
return mapping.findForward("success");
}
} |
原文地址:http://www.developer.com/java/ejb/article.php/2214681
這就是一起綁定的所有東西,他們總是與Struts一起,放在struts-config.xml 文件內:
<struts-config>
<form-beans>
<form-bean name="customerForm" type="jdj.article1.Customer" />
</form-beans>
<action-mappings>
<action path="/addCustomer" type="article1.AddCustomerAction"
name="customerForm" scope="request"
input="/addCustomer.jsp">
<forward name="success" path="/addCustomerSucceeded.jsp"
redirect="false" />
</action>
</action-mappings>
<message-resources parameter="ApplicationResources" />
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property value="/WEB-INF/validator-rules.xml"
property="pathnames" />
struts-config.xml</plug-in></struts-config>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<form-beans>
<form-bean name="customerForm" type="article1.CustomerForm" />
</form-beans>
<action-mappings>
<action path="/addCustomer" type="article1.AddCustomerAction"
name="customerForm" scope="request" input="/customer.jsp">
<forward name="success" path="/addCustomerSucceeded.jsp"
redirect="false" />
</action>
</action-mappings>
<message-resources parameter="ApplicationResources" />
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property value="/WEB-INF/validator-rules.xml"
property="pathnames" />
</plug-in>
</struts-config>
|
customerForm鏈接到剛剛定義的CustomerForm 類上, /addCustomer動作也是定義用來使用該表格和使用article1.AddCustomerAction類來處理請求。
當你將表格放在了你的瀏覽器上,你需要填寫下列空白表格:

如果你提交了無任何實際內容的表格,就會出現下列內容:

當你認真填寫了表格并提交后,在你的Web容器日志文件內(在Tomcat 下為catalina.out )就會出現下列內容:
lastName = Bush
firstName = George
street = 1600 Pennsylvania Avenue NW
city = Washington
state = DC
postalCode = 20500
phone = 2024561414 |
至此,這都是人人熟知的Struts。但是,通過使用Struts 1.1的某些新特征,你可以徹底的刪除原本需要編寫的大量代碼。例如: 我們使用Dynaform擴展,就不需要ActionForm類。如果這樣的話,我們需要修改struts-config.xml 中的customerForm 的定義,以便使用org.apache.struts.action.DynaActionForm類(為了這篇指南,我們實際上將創建一個新的類和JSP頁,這樣你就能夠比較他們兩個)
通過使用DynaActionForm,你獲得到form-property XML標記的訪問,這個標記允許你直接定義struts-config.xml內表格的屬性。它看起來如下:
<form-bean name="dynaCustomerForm"
type="org.apache.struts.action.DynaActionForm">
<form-property name="lastName" type="java.lang.String"/>
<form-property name="firstName" type="java.lang.String"/>
<form-property type="java.lang.String" name="street"/>
<form-property name="city" type="java.lang.String"/>
<form-property name="state" type="java.lang.String"/>
<form-property name="postalCode" type="java.lang.String"/>
</form-bean> |
這就不需要對JSP頁做任何修改;DynaForms的使用對Struts HTML標記庫是透明的。你確實需要對Action稍微修改一下,但是,因為你不能夠再將傳遞到execute()方法內的表格直接傳遞給擁有存取器(用于你的數據的GET和SET方法)的類中。相反,你需要將表格傳遞給DynaActionForm,并且需要使用普通的get(fieldname)存取器。所以Action的新版本看起來如下:
article1.AddDynaCustomerAction
package article1;
import org.apache.struts.action.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
public class AddDynaCustomerAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException{
DynaActionForm custForm = (DynaActionForm) form;
System.out.println("lastName = " + custForm.get("lastName"));
System.out.println("firstName = " + custForm.get("firstName"));
System.out.println("street = " + custForm.get("street"));
System.out.println("city = " + custForm.get("city"));
System.out.println("state = " + custForm.get("state"));
System.out.println("postalCode = "
+ custForm.get("postalCode"));
System.out.println("phone = " + custForm.get("phone"));
return mapping.findForward("success");
}
} |
如你所見,它完全刪除了整個類(ActionForm)。但是,我們喪失了其他的功能:校驗表格數據的能力。有兩個方法可以重新獲得這個功能。一個方法就是創建一個類,它產生子類DynaActionForm并且實現validate()方法。在我們的范例中,它看起來如下:
article1.DynaCustomerForm
package article1;
import org.apache.struts.action.*;
import javax.servlet.http.HttpServletRequest;
public class DynaCustomerForm extends DynaActionForm {
protected boolean nullOrBlank (String str) {
return ((str == null) || (str.length() == 0));
}
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if (nullOrBlank((String)this.get("lastName"))) {
errors.add("lastName",
new ActionError("article1.lastName.missing"));
}
if (nullOrBlank((String)this.get("firstName"))) {
errors.add("firstName",
new ActionError("article1.firstName.missing"));
}
if (nullOrBlank((String)this.get("street"))) {
errors.add("street",
new ActionError("article1.street.missing"));
}
if (nullOrBlank((String)this.get("city"))) {
errors.add("city", new ActionError("article1.city.missing"));
}
if (nullOrBlank((String)this.get("state"))) {
errors.add("state",
new ActionError("article1.state.missing"));
}
if (nullOrBlank((String)this.get("postalCode"))) {
errors.add("postalCode",
new ActionError("article1.postalCode.missing"));
}
if (nullOrBlank((String)this.get("phone"))) {
errors.add("phone", new ActionError("article1.phone.missing"));
}
return errors;
}
} |
請再次注意:我們需要使用get()存取器,而不是直接訪問實際變量。我們也需要修改struts-config.xml 中表格的定義,以便用這個新類來取代一般的DynaActionForm 類。如果這樣的話,就會重新獲得校驗功能。但是,我們得重新為每個表格定義明確的類。在Struts 1.1下進行校驗,我推薦的方法是使用Struts Validator 框架,它將在后續文章中進行說明。
在本系列的下一篇文章中,我們將看到DynaForms 的更高級的用途。特別是,我們將教你如何使用編入索引的屬性和beans排列來實現復雜的細節繁瑣的表格。
關于作者 James Turner 是Benefit Systems有限公司軟件開發總監。他對Apache Struts 項目頗有貢獻。他已經出版了兩本面向WEB的JAVA技術的書:MySQL and JSP Web Applications, 和Struts Kick Start。他的第三本書,Java Server Faces Kick Start,在2003年冬季由Sams出版發行。