4. استفاده از فرمهای پویا
4.1. اعلام یک فرم پویا
ما دیدهایم که Struts از اشیاء ActionForm برای ذخیره مقادیر فرمهای HTML که توسط سرولتهای مختلف برنامه پردازش میشوند، استفاده میکند. برای هر فرم در برنامهٔ ما، باید کلاسی مشتقشده از ActionForm ایجاد کنیم. این کار میتواند بهسرعت نسبتاً دستوپاگیر شود، زیرا برای هر فیلد xx باید دو متد بنویسیم: setXx و getXx. Struts به ما اجازه میدهد از فرمها استفاده کنیم
- که ساختار آن در فایل struts-config.xml در بخش <form-beans> اعلام میشود
- و که به صورت پویا توسط محیط Struts بر اساس ساختار اعلامشده ایجاد میشوند
بنابراین، کلاسی که برای ذخیره مقادیر 'name' و 'age' در برنامه **strutspersonne** استفاده میشود، میتواند به صورت زیر تعریف شود:
<form-beans>
<form-bean name="frmPersonne" type="org.apache.struts.actions.DynaActionForm">
<form-property name="nom" type="java.lang.String" initial=""/>
<form-property name="age" type="java.lang.String" initial=""/>
</form-bean>
</form-beans>
برای هر فیلد در فرم، یک تگ <form-property> با دو ویژگی تعریف میشود:
- name: نام فیلد
- type: نوع جاوا آن
از آنجا که مقادیر در یک فرم ارسالشده توسط یک کلاینت وب رشتههای کاراکتری هستند، رایجترین انواع java.lang.String برای فیلدهای تکمقدار و java.lang.String[] برای فیلدهای چندمقدار (تیکباکسهایی با نام یکسان، لیستهای چندگزینهای و غیره) هستند. هر دو کلاس DynactionForm و ActionForm دارای متد validate هستند که هیچ کاری انجام نمیدهد. برای اینکه آنها اعتبار پارامترهای فرم را بررسی کنند، باید از آنها ارثبری کنید و متد validate را خودتان بنویسید. بنابراین اعلان فرم به شکل زیر خواهد بود:
<form-beans>
<form-bean name="frmPersonne" type="istia.st.struts.personne.PersonneDynaForm">
<form-property name="nom" type="java.lang.String" initial=""/>
<form-property name="age" type="java.lang.String" initial=""/>
</form-bean>
</form-beans>
ما باید کلاس istia.st.struts.personne.PersonneDynaForm را ایجاد کنیم.
4.2. ایجاد کلاس DynaActionForm مرتبط با فرم پویا
در بالا، کلاس istia.st.struts.personne.PersonneDynaForm را به فرم (نام، سن) متصل کردیم. اکنون این کلاس را مینویسیم:
package istia.st.struts.personne;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class PersonneDynaForm extends DynaActionForm {
//اعتبارسنجی
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
// مدیریت خطا
ActionErrors erreurs = new ActionErrors();
//نام نباید خالی باشد
String nom = (String)this.get("nom");
if (nom == null || nom.trim().equals("")) {
erreurs.add("nomvide", new ActionError("personne.formulaire.nom.vide"));
}
// سن نباید خالی باشد
String age = (String)this.get("age");
if (age == null || age.trim().equals("")) {
erreurs.add("agevide", new ActionError("personne.formulaire.age.vide"));
}
else {
// سن باید یک عدد صحیح مثبت باشد
if (!age.matches("^\\s*\\d+\\s*$")) {
erreurs.add("ageincorrect", new ActionError("personne.formulaire.age.incorrect", age));
// بازگرداندن فهرست خطاها
}
} //اگر
// فهرست خطاها را بازمیگرداند
return erreurs;
}
}//کلاس
نکات قابل توجه به شرح زیر است:
- این کلاس از DynaActionForm مشتق شده است
- متد validate کلاس DynaActionForm بازنویسی شده است. هنگامی که توسط کنترلکننده Struts اجرا میشود، شیء PersonneDynaForm ساخته میشود. این شیء شامل یک دیکشنری است که کلیدهای آن فیلدهای فرم «name» و «age» و مقادیر آن، مقادیر این فیلدها هستند. برای دسترسی به یک فیلد در متدهای DynaActionForm، از متد Object get(String nomDuChamp) استفاده میشود. اگر میخواهید برای یک فیلد مقداری را تنظیم کنید، میتوانید از متد void set(String nomDuChamp, Object value) استفاده کنید. لطفاً برای تعریف کامل به تعریف کلاس DynaActionForm مراجعه کنید.
- پس از بازیابی مقادیر فیلدهای «name» و «age» در فرم، متد `validate` تفاوتی با متدی که هنگام مرتبط کردن فرم با یک شیء `ActionForm` نوشته شده بود، ندارد.
4.3. کلاس جدید FormulaireAction
فایل پیکربندی، اکشن اصلی زیر را تعریف میکند:
...
<form-beans>
<form-bean name="frmPersonne" type="istia.st.struts.personne.PersonneDynaForm">
<form-property name="nom" type="java.lang.String" initial=""/>
<form-property name="age" type="java.lang.String" initial=""/>
</form-bean>
</form-beans>
....
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
type="istia.st.struts.personne.FormulaireAction"
>
<forward name="reponse" path="/reponse.do"/>
</action>
این تعریف مشابه برنامه strutspersonne است. عملیات /main توسط یک شی از نوع FormulaireAction انجام میشود. این شی قبلاً مقادیر را از فرم frmPersonne در یک شی از نوع FormulaireBean دریافت میکرد. اکنون این مقادیر را در یک شیء از نوع PersonneDynaForm دریافت میکند. بنابراین کلاس باید به صورت زیر بازنویسی شود:
package istia.st.struts.personne;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import javax.servlet.ServletException;
import istia.st.struts.personne.PersonneDynaForm;
public class FormulaireAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException {
//فرم معتبر است؛ در غیر این صورت، به این نقطه نمیرسیدیم
PersonneDynaForm formulaire=(PersonneDynaForm)form;
request.setAttribute("nom",formulaire.get("nom"));
request.setAttribute("age",formulaire.get("age"));
return mapping.findForward("reponse");
}//اجرا
}
نکات زیر باید مورد توجه قرار گیرند:
- ما باید کلاس PersonneDynaForm را که حاوی دادههای فرم است، وارد کنیم تا به تعریف آن دسترسی پیدا کنیم
- متد `execute` با استفاده از متد `[DynaActionForm].get` مقادیر پارامترهای فرم را بازیابی میکند.
در مقایسه با کلاس FormulaireAction در اپلیکیشن strutspersonne، تنها روش دسترسی به مقادیر فرم تغییر کرده است.
4.4. استقرار و تست اپلیکیشن strutspersonne1
4.4.1. ایجاد زمینه
ما این برنامهٔ جدید را «strutspersonne1» نامگذاری کردهایم. در فایل Tomcat به آدرس <tomcat>\conf\serveur.xml یک تعریف جدید ایجاد میکنیم:
پس از انجام این کار، تامکت باید مجدداً راهاندازی شود. میتوان با درخواست URL: زمینه را تأیید کرد:
http://localhost:8080/strutspersonne1/

4.4.2. ویوها
پوشه 'views' را از برنامه 'strutspersonne' به پوشه برنامه 'strutspersonne1' کپی کنید. دلیل آن این است که ویوها تغییر نکردهاند.

4.4.3. کامپایل کردن کلاسها
ما باید دو کلاس ایجاد کنیم: PersonneDynaForm و FormulaireAction که دومی از اولی استفاده میکند. میتوانیم آنها را با استفاده از یک پروژه JBuilder ایجاد و کامپایل کنیم:

4.4.4. پوشه WEB-INF
ما پوشه WEB-INF را از برنامه strutspersonne به پوشه برنامه strutspersonne1 کپی خواهیم کرد. چند فایل تغییر خواهند کرد:

فایل پیکربندی struts-config.xml به شرح زیر درمیآید:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!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="frmPersonne" type="istia.st.struts.personne.PersonneDynaForm">
<form-property name="nom" type="java.lang.String" initial=""/>
<form-property name="age" type="java.lang.String" initial=""/>
</form-bean>
</form-beans>
<action-mappings>
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
type="istia.st.struts.personne.FormulaireAction"
>
<forward name="reponse" path="/reponse.do"/>
</action>
<action
path="/erreurs"
parameter="/vues/erreurs.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
<action
path="/reponse"
parameter="/vues/reponse.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
<action
path="/formulaire"
parameter="/vues/formulaire.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
</action-mappings>
<message-resources parameter="ressources.personneressources"/>
</struts-config>
این فایل با فایل برنامه strutspersonne یکسان است، به جز تعریف فرم پویا (بخش محصور).
در پوشه WEB-INF/classes، کلاسهای کامپایلشده توسط JBuilder را قرار میدهیم:

در پوشه WEB-INF\classes\resources، فایل پیام را قرار دهید. این فایل تغییری نکرده است.
personne.formulaire.nom.vide=<li>Vous devez indiquer un nom</li>
personne.formulaire.age.vide=<li>Vous devez indiquer un age</li>
personne.formulaire.age.incorrect=<li>L'âge [{0}] est incorrect</li>
errors.header=<ul>
errors.footer=</ul>

4.5. آزمایشها
ما برای آزمایشها آمادهایم. در زیر چند اسکرینشات آمده است که از خواننده دعوت میشود آنها را بازتولید کند.
ما به دنبال URLhttp://localhost:8080/strutspersonne1/formulaire.do هستیم:

از دکمه [Envoyer] بدون پر کردن فیلدها استفاده کنید:

ما دوباره تلاش میکنیم، اما در فیلد «سن» خطایی وجود دارد:

پاسخ زیر بازگردانده میشود:

بیایید دوباره تلاش کنیم، این بار با وارد کردن مقادیر صحیح:

پاسخ زیر دریافت میشود:

4.6. نتیجهگیری
استفاده از فرمهای پویا نوشتن کلاسهایی مانند ActionForm را که مسئول ذخیره مقادیر فرم هستند، آسانتر میکند. میتوانیم سادهسازی مدیریت فرم را یک قدم فراتر ببریم. در اپلیکیشن strutspersonne1، ما یک کلاس PersonneDynaForm برای بررسی اعتبار مقادیر فرم (نام، سن) ایجاد کردهایم. در عمل، برخی بررسیها به طور مکرر تکرار میشوند: خالی نبودن فیلد، مطابقت فیلد با یک عبارت منظم خاص، عددی بودن فیلد، فیلد تاریخ و غیره. این نوع اعتبارسنجی استاندارد را میتوان سپس در فایل پیکربندی struts-config.html مشخص کرد. اگر همه اعتبارسنجیهای مورد نیاز «استاندارد» باشند، دیگر نیازی به نوشتن کلاسی برای فرم نیست. این چیزی است که اکنون به آن خواهیم پرداخت.