明輝手游網(wǎng)中心:是一個免費提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

Struts的動態(tài)表單的應(yīng)用

[摘要]By James M. Turner 這篇文章以實例代碼來闡述Dynaforms在struts1.1種的引用??譯者注 如果你使用過struts先前的版本,你就會注意到你需要花費大量的時候來寫ActionForm類文件,而這些類文件對于struts都是非常關(guān)鍵的(它充當“View”的一部分),通常...
By James M. Turner


這篇文章以實例代碼來闡述Dynaforms在struts1.1種的引用??譯者注


如果你使用過struts先前的版本,你就會注意到你需要花費大量的時候來寫ActionForm類文件,而這些類文件對于struts都是非常關(guān)鍵的(它充當“View”的一部分),通常它的結(jié)構(gòu)就是bean properties在加上一個validate方法(有時還有reset方法)。

隨著struts1.1版本的推出,開發(fā)員有了另外一種方法來完成前面的任務(wù):使用DynaBeans。DynaBeans動態(tài)生成Java Beans。這就意味著我們可以通過配置(通常利用xml)

來生成formbean而不是在formbean中硬編碼。

為了了解DynaBeans(struts中為Dynaforms)是如何工做的,讓我們看一個簡單的表單,字段有:name,address,telephone等,下面的代碼為通常的寫法(沒有使用Dynaforms)。


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;
}
}


看到上邊的寫法(這么長一段代碼[雖然大多的工具都可以自動生成set和get方法]感想如何?如果要為每一個表單配備一個formbean,那么將是一件多了令人痛苦的事情??譯者注),你知道了它是一個標準的JavaBean,只是多了一個validate方法,validate方法確保client斷的輸入都是合法的。


相應(yīng)的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>


相應(yīng)的action也沒有復(fù)雜的業(yè)務(wù)代碼,只是將從client端傳過來的值打印到控制臺。

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");
}
}



下面看看struts-config.xml的配置,struts利用該配置文件將上述文件聯(lián)系到一起來協(xié)同完成任務(wù)。


<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來引用CustemerForm類, “/addCustomer”action使用customerForm并且觸發(fā)article1.AddCustomerAction來處理請求。

到現(xiàn)在為止,上邊代碼熟悉struts得都應(yīng)該很熟悉但是,如果應(yīng)用struts1.1的新特性,你將會用更少的代碼來完成上述同樣的功能。使用Dynaforms,我們應(yīng)該更改customerForm在struts-config.xml中信息來使用org.apache.struts.action.DynaActionForm (為了便于讀者比較使用前后的差別,我們將使用新的類新的jsp頁面來完成同樣的功能)


使用DynaActionForm,你可以利用form-property xml標簽,它允許你在struts-config.xml中定義formbean的屬性元素。以我們的例子來說,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頁面沒有任何的影響。不過你要對于原來的action進行稍微的改動應(yīng)為:你現(xiàn)在已經(jīng)不在向execute()中傳遞formbean(沒有g(shù)et set方法),所以 你應(yīng)該把form轉(zhuǎn)型到DynaActionForm,然后利用方法get(filename)來取得client端數(shù)據(jù)新的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,然而我們也“丟失”了一些其他的,譬如:嚴整輸入合法性的問題。有兩種方法可以恢復(fù)校驗功能:一是創(chuàng)建一個DynaActionForm的子類,然后在子類中實現(xiàn)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;
}

}
如果是這樣,我們就要更改struts-config.xml來使用DynaActionForm的子類,這樣的效果似乎是又回到了先前的樣子(為每一個表單寫DynaActionForm),呵呵。。。

所以推薦的做法是使用struts1.1種的Validator Framework,這方面的內(nèi)容在以后的文章中在說明。


關(guān)于作者:

James Turner is the owner and manager of Black Bear Software, LLC, which specializes in custom Java-based e-Commerce and CRM solutions delivery. He is also the author of "MySQL and JSP Web Applications: Data-Driven Programming Using Tomcat and MySQL" (ISBN: 0672323095) and is the co-author of "Struts: Kick Start" (ISBN: 0672324725), which will be published in November. He can be reached at turner@blackbear.com.