Struts的动态表单的应用
如果你使用过struts先前的版本,你就会注意到你需要花费大量的时候来写ActionForm类文件,而这些类文件对于struts都是非常关键的(它充当“View”的一部分),通常它的结构就是bean properties在加上一个validate方法(有时还有reset方法)。
随着struts1.1版本的推出,开发员有了另外一种方法来完成前面的任务:使用DynaBeans。DynaBeans动态生成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断的输入都是合法的。 相应的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也没有复杂的业务代码,只是将从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利用该配置文件将上述文件联系到一起来协同完成任务。 <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并且触发article1.AddCustomerAction来处理请求。 到现在为止,上边代码熟悉struts得都应该很熟悉但是,如果应用struts1.1的新特性,你将会用更少的代码来完成上述同样的功 能。使用Dynaforms,我们应该更改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进行稍微的改动应为:你现在已经不在向execute()中传递formbean(没有get set方法),所以 你应该把form转型到DynaActionForm,然后利用方法get(filename)来取得client端数据新的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; } } 如果是这样,我们就要更改struts-config.xml来使用DynaActionForm的子类,这样的效果似乎是又回到了先前的样子(为每一个表单写DynaActionForm) |