Skip to content

2. برنامهٔ «شخص» با Struts

ما قبلاً یک اپلیکیشن «شخص» را با رویکرد سنتی، با سرولت‌ها و صفحات JSP پوشش داده‌ایم. اکنون پیشنهاد می‌کنیم که همین اپلیکیشن را برای معرفی Struts استفاده کنیم.

2.1. نحوه کار برنامه

بیایید به‌طور خلاصه مرور کنیم که اپلیکیشن «person» که توسعه دادیم چگونه کار می‌کند. این اپلیکیشن شامل موارد زیر است:

  • یک سروِلِت اصلی. این سروِلِت تمام منطق برنامه را مدیریت می‌کند.
  • سه صفحه JSP: formulaire.personne.jsp، reponse.personne.jsp، erreurs.personne.jsp

کاربرد به شرح زیر عمل می‌کند. می‌توان از طریق URL http://localhost:8080/personne/main به آن دسترسی داشت. در این URL، فرم ارائه‌شده توسط صفحه formulaire.personne.jsp نمایش داده می‌شود:

Image

کاربر فرم را پر می‌کند و روی دکمه ارسال [Envoyer] کلیک می‌کند. دکمه [Rétablir] یک دکمه بازنشانی است، c.a.d، که سند را به حالتی که در آن دریافت شده بود بازمی‌گرداند. دکمه [Effacer] یک دکمه استاندارد است. کاربر باید نام و سن معتبر ارائه دهد. در غیر این صورت، یک صفحه خطا از طریق صفحات JSP و erreurs.personne.jsp برای او ارسال می‌شود. در اینجا چند مثال آورده شده است:

تبادل شماره ۱

demande
réponse

اگر لینک [Retour au formulaire] را دنبال کنید، دقیقاً همان‌طور که آن را رها کرده‌اید، خواهید یافت:

تبادل شماره ۲

demande
réponse

اگر کاربر داده‌های صحیح را ارسال کند، برنامه از طریق صفحه JSP reponse.personne.jsp پاسخ می‌دهد.

تبادل شماره ۱

demande
réponse

اگر لینک [Retour au formulaire] را دنبال کنید، دقیقاً همان‌طور که آن را رها کرده‌اید، خواهید یافت:

تبادل شماره ۲

demande
réponse

2.2. معماری Struts برنامه

ما معماری زیر را برای Struts اتخاذ خواهیم کرد:

  • سه نما وجود خواهد داشت
  • کنترلر همان مورد ارائه‌شده توسط Struts خواهد بود
  • FormulaireBean کلاسی است که مسئول ذخیرهٔ مقادیر فرم ارائه‌شده توسط نمای formulaire.personne.jsp است.
  • FormulaireAction کلاسی است که مسئول پردازش مقادیر از FormulaireBean و مشخص کردن صفحه پاسخ برای ارسال است:
    • view erreurs.personne.jsp اگر داده‌های فرم نادرست باشد
    • در غیر این صورت، ویوی reponse.personne.jsp

برای توسعه‌دهنده، این کار شامل نوشتن کد است:

  • سه نما
  • بیان FormulaireBean مرتبط با فرم
  • کلاس FormulaireAction مسئول پردازش فرم

2.3. کامپایل کلاس‌های مورد نیاز برای برنامهٔ Struts

برای کامپایل کلاس‌های مورد نیاز برای برنامهٔ ما، از JBuilder استفاده خواهیم کرد. این ابزار با فایلی به نام JDK کار می‌کند که شامل کلاس‌های مورد نیاز برای برنامه‌های Struts نیست. می‌توانیم JBuilder را به شرح زیر پیکربندی کنیم:

  • گزینه Tools / پیکربندی JDKs (Configure JDK)

Image

  • از دکمه [Add/Ajouter] برای افزودن فایل‌های .jar ارائه‌شده توسط Struts به آرشیوهای کلاس JBuilder استفاده کنید. اگر آرشیو Struts را به هارد دیسک خود استخراج کرده‌اید، می‌توانید تمام فایل‌های .jar موجود در پوشه <struts>/lib را به JBuilder اضافه کنید:

Image

شما می‌توانید تمام فایل‌های .jar فوق را به آرشیوهای JBuilder اضافه کنید. ما قبلاً دیده‌ایم که تام‌کت نیز به دسترسی به آرشیوهای Struts نیاز دارد. برای تام‌کت 4.x، می‌توانید فایل‌های .jar Struts را در <tomcat4>\common\lib قرار دهید. برای تام‌کت 5.x، می‌توانید آن‌ها را در <tomcat5>\shared\lib قرار دهید. سپس می‌توانید JBuilder را پیکربندی کنید تا فایل‌های .jar استراژ (Struts) را در همان مکانی که Tomcat قرار دارد جستجو کند. این کاری است که در اسکرین‌شاتی که کمی پیش فایل‌های .jar JBuilder را نشان می‌داد، انجام شده بود. آن‌ها از <tomcat5>\shared\lib گرفته شده بودند.

بنابراین، اگر هنگام کامپایل یک کلاس، JBuilder گزارش داد که نمی‌تواند یک کلاس Struts را پیدا کند، دو مورد را بررسی کنید:

  • املا‌ی کلاس
  • فایل‌های .jar مورد استفاده توسط JBuilder. تمام فایل‌های .jar Struts باید گنجانده شوند.

2.4. نماهای برنامه strutspersonne

سه نمای این برنامه به شرح زیر است:

  • formulaire.personne.jsp: فرم وارد کردن نام و سن شخص را نمایش می‌دهد
  • reponse.personne.jsp: مقادیر واردشده را در صورت معتبر بودن نمایش می‌دهد
  • erreurs.personne.jsp: خطاها را نمایش می‌دهد

2.4.1. ویوی erreurs.personne.jsp

این نما که فهرستی از خطاها را نمایش می‌دهد، به صورت زیر تعریف خواهد شد:

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Les erreurs suivantes se sont produites</h2>
        <html:errors/>
    <html:link page="/formulaire.do">
            Retour au formulaire
        </html:link>    
  </body>
</html>

در این کد دو ویژگی جدید وجود دارد:

  1. وجود تگ‌های <html:XX/> که تگ‌های HTML نیستند. در واقع می‌توان کتابخانه‌هایی از تگ‌های JSP ایجاد کرد که وقتی صفحه JSP به یک سرولت تبدیل می‌شود، به کد جاوا تبدیل می‌شوند.
  2. صفحه JSP باید کتابخانه‌های تگی را که استفاده می‌کند اعلام کند. این کار در اینجا با خط
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

این خط دو مورد اطلاعات را ارائه می‌دهد:

  • uri: مکان فایلی که قوانین مربوط به استفاده از کتابخانه را مدیریت می‌کند. فایل struts-html.tld در توزیع Struts ارائه شده است. در مثال بالا، این فایل در پوشه WEB-INF قرار داده می‌شود.
  • پیش‌وند: شناسه‌ای که در کد برای پیش‌وندگذاری تگ‌های کتابخانه استفاده می‌شود. این کار به جلوگیری از تداخل نام‌ها که ممکن است هنگام استفاده همزمان از چندین کتابخانه تگ ایجاد شود، کمک می‌کند. ممکن است دو تگ با نام یکسان در دو کتابخانه مختلف وجود داشته باشند. با دادن یک پیش‌وند متفاوت به هر کتابخانه، هرگونه ابهام برطرف می‌شود.
  • تگ <html:errors> فهرست خطاهایی را که توسط کنترل‌کننده Struts به آن ارسال شده است، نمایش می‌دهد.
  • تگ <html:link> یک لینک تولید می‌کند که به /C/page اشاره دارد، جایی که
    • C نمایانگر زمینهٔ برنامه است
    • 'page' همان URL مشخص‌شده در ویژگی 'page' تگ است

برچسب

    <html:link page="/formulaire.do">
            Retour au formulaire
        </html:link>
<a href="/C/formulaire.do">Retour au formulaire</a>

که در آن C زمینهٔ برنامه است

2.4.2. آزمایش نما erreurs.personne.jsp

  • فایل erreurs.personne.jsp در پوشه 'views' اپلیکیشن strutspersonne قرار می‌گیرد:

Image

  • فایل struts-html.tld از توزیع Struts (<struts>/lib) گرفته شده و در WEB-INF قرار داده شده است:

Image

  • فایل 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>
    <action-mappings>
      <action
          path="/main"
          parameter="/vues/main.html"
          type="org.apache.struts.actions.ForwardAction"
      />
      <action
          path="/erreurs"
          parameter="/vues/erreurs.personne.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
    </action-mappings>
</struts-config>

ما یک URL /errors جدید در فایل پیکربندی ایجاد می‌کنیم که قرار است توسط کنترل‌کننده Struts مدیریت شود. URL /erreurs.do به view /views/erreurs.personne.jsp هدایت خواهد شد. فایل struts-config.xml در پوشه WEB-INF قرار می‌گیرد.

  • ما تام‌کت را مجدداً راه‌اندازی می‌کنیم تا فایل جدید struts-config.xml شناسایی شود، سپس URL http://localhost:8080/strutspersonne/erreurs.do را درخواست می‌کنیم:

Image

تگ <html:errors/> هیچ خروجی‌ای تولید نکرد. این امر قابل انتظار است، زیرا اکشن ForwardAction لیست خطاهای مورد نیاز این تگ را تولید نکرده است. با این حال، پاسخ بالا نشان می‌دهد که نمای JSP ما حداقل از نظر نحوی صحیح است؛ در غیر این صورت، ما یک صفحه خطا دریافت می‌کردیم. بیایید کد HTML دریافت‌شده توسط مرورگر را بررسی کنیم (View/Source):

<html>
    <head>
      <title>Personne - erreurs</title>
  </head>
  <body>
      <h2>Les erreurs suivantes se sont produites</h2>        
    <a href="/strutspersonne/formulaire.do">Retour au formulaire</a>    
  </body>
</html>

به لینک تولید شده توسط تگ <html:link> توجه کنید. کانتکست /strutspersonne به طور خودکار در لینک گنجانده شده است. این امکان را می‌دهد که برنامه را از یک کانتکست به کانتکست دیگر (مثلاً هنگام تعویض ماشین‌ها) منتقل کنید، بدون اینکه نیازی به تغییر لینک‌های تولید شده توسط <html:link> باشد.

2.4.3. نما reponse.personne.jsp

این نما که مقادیر وارد شده در فرم را تأیید می‌کند، به شرح زیر است:

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

<%
     //بازیابی داده‌های «name» و «age»
  //String name = (String)request.getAttribute("name");
  String nom="jean";

   //String name = (String)request.getAttribute("name"); 
  String age="24"; 
%>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Personne - réponse</h2>
    <hr>
    <table>
        <tr>
          <td>Nom</td>
        <td><%= nom %>
      </tr>
        <tr>
          <td>Age</td>
        <td><%= age %>
      </tr>
    </table>      
    <br>
    <html:link page="/formulaire.do">
            Retour au formulaire
        </html:link>    
  </body>
</html>

این صفحه دو مقدار اطلاعاتی، [nom] و [age]، را نمایش می‌دهد که توسط کنترلر در شیء از پیش تعریف‌شده **request به آن ارسال خواهند شد. در اینجا ما در حال انجام آزمایشی هستیم که در آن کنترلر فرصت تعیین مقادیر برای [nom] و [age] را نخواهد داشت. بنابراین این دو مقدار را با مقادیر دلخواه اولیه می‌کنیم. علاوه بر این، در اینجا نیز لینک بازگشت به فرم توسط تگ <html:link**> ایجاد می‌شود.

2.4.4. آزمایش نمای reponse.personne.jsp

  • فایل reponse.personne.jsp در پوشه 'views' اپلیکیشن strutspersonne قرار داده شده است:

Image

  • فایل 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>
    <action-mappings>
      <action
          path="/main"
          parameter="/vues/main.html"
          type="org.apache.struts.actions.ForwardAction"
      />
      <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-mappings>
</struts-config>

ما یک URL/response جدید در فایل پیکربندی ایجاد می‌کنیم که قرار است توسط کنترلر Struts پردازش شود. URL /reponse.do به نمای /vues/reponse.personne.jsp هدایت خواهد شد. فایل struts-config.xml در پوشه WEB-INF قرار داده می‌شود.

  • ما تام‌کت را مجدداً راه‌اندازی می‌کنیم تا فایل جدید struts-config.xml شناسایی شود، سپس URL http://localhost:8080/strutspersonne/erreurs.do را درخواست می‌کنیم:

Image

دقیقاً همان چیزی را که انتظار داشتیم دریافت می‌کنیم.

2.4.5. ویوی formulaire.personne.jsp

این نما فرم وارد کردن نام و سن کاربر را نمایش می‌دهد. کد آن، JSP، به شرح زیر است:

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

<html>
    <meta http-equiv="pragma" content="no-cache"> 
    <head>
      <title>Personne - formulaire</title>
    <script language="javascript">
        function effacer(){
          with(document.frmPersonne){
            nom.value="";
          age.value="";
        }
      }
    </script>
  </head>

  <body>
      <center>
        <h2>Personne - formulaire</h2>
      <hr>
      <html:form action="/main" name="frmPersonne" type="istia.st.struts.personne.FormulaireBean">
          <table>
            <tr>
              <td>Nom</td>
            <td><html:text property="nom" size="20"/></td>
          </tr>
          <tr>
              <td>Age</td>
            <td><html:text property="age" size="3"/></td>
          </tr>
            <tr>
        </table>
        <table>
            <tr>
              <td><html:submit value="Envoyer"/></td>
            <td><html:reset value="Rétablir"/></td>
            <td><html:button property="btnEffacer" value="Effacer" onclick="effacer()"/></td>
          </tr>
        </table>
      </html:form>
    </center>
  </body>
</html>

ما کتابخانه تگ struts-html.tld را در نمای خطاها پیدا می‌کنیم. تگ‌های جدید ظاهر می‌شوند:

html:form
هم برای تولید تگ HTML <form> و هم برای ارائه اطلاعات به کنترولری که این فرم را پردازش خواهد کرد، استفاده می‌شود:
action
آدرس URL که مقادیر فرم به آن ارسال خواهد شد
name
نام فرم HTML. این همچنین نام بیانی است که مقادیر فرم را ذخیره خواهد کرد
type
نام کلاسی که باید برای به‌دست‌آوردن bean ذخیره‌سازی فرم instantiate شود
توجه داشته باشید که متد ارسال پارامترهای فرم (GET/POST) به کنترلر مشخص نشده است. این کار را می‌توان با استفاده از ویژگی 'method' انجام داد. در صورت عدم وجود این ویژگی، متد POST به‌طور پیش‌فرض استفاده می‌شود.
html:text
برای تولید تگ <input type="text" value="..."> استفاده می‌شود:
property
نام فیلد در فرم‌بین است که با فیلد ورودی مرتبط خواهد شد. هنگامی که فرم به سرور ارسال می‌شود (کلاینت → سرور)، فیلد بین مقدار فیلد ورودی را دریافت می‌کند. هنگامی که فرم نمایش داده می‌شود (سرور → کلاینت)، مقدار موجود در فیلد بین در فیلد ورودی نمایش داده می‌شود.
html:submit
برای تولید تگ HTML <input type="submit"...> استفاده می‌شود
html:reset
برای تولید تگ HTML <input type="reset"...> استفاده می‌شود.
html:button
برای تولید تگ HTML <input type="button"...> استفاده می‌شود

2.4.6. بیان مرتبط با فرم formulaire.personne.jsp

  • با Struts، هر فرم باید با یک bean مرتبط باشد که مسئول ذخیره مقادیر فرم و نگهداری آن‌ها در جلسه جاری است. یک bean یک کلاس Java است که باید از سینتکس خاصی پیروی کند. bean مرتبط با یک فرم باید از کلاس ActionForm تعریف‌شده در کتابخانه‌های Struts ارث ببرد:
public class FormulaireBean extends ActionForm {
  • نام‌های ویژگی‌های بین باید با فیلدهای فرم (ویژگی‌های `property` در تگ‌های `html:text` فرم) مطابقت داشته باشند. بنابراین، بر اساس کد فرم قبلی، بین باید دو فیلد به نام‌های `nom` و `age` داشته باشد.
  • برای هر فیلد XX در فرم، باید دو متد در بین (bean) تعریف شود:
    • public void setXX(Type value): برای اختصاص دادن مقدار به ویژگی XX
    • نوع getXX(): برای بازیابی مقدار فیلد XX

بیان مرتبط با فرم قبلی می‌تواند به شکل زیر باشد:

package istia.st.struts.personne;

import org.apache.struts.action.ActionForm;

public class FormulaireBean extends ActionForm {
   // name
  private String nom = null;
  public String getNom() {
    return nom;
  }
  public void setNom(String nom) {
    this.nom = nom;
  }

   // سن
  private String age = null;
  public String getAge() {
    return age;
  }
  public void setAge(String age) {
    this.age = age;
  }
}

ما این کلاس‌ها را با استفاده از JBuilder کامپایل خواهیم کرد.

2.4.7. آزمایش نما formulaire.personne.jsp

فایل formulaire.personne.jsp در پوشه 'views' اپلیکیشن StrutsPersonne قرار داده شده است:

Image

  • فایل 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>
    <action-mappings>
      <action
          path="/main"
          parameter="/vues/main.html"
          type="org.apache.struts.actions.ForwardAction"
      />
      <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>
</struts-config>

ما یک فرم جدید URL را در فایل پیکربندی ایجاد می‌کنیم که قرار است توسط کنترلر Struts پردازش شود. URL /formulaire.do به نمای /vues/formulaire.personne.jsp هدایت خواهد شد. فایل struts-config.xml در پوشه WEB-INF قرار می‌گیرد.

  • کلاس FormulaireBean را در WEB-INF/classes قرار می‌دهیم:

Image

  • تام‌کت را مجدداً راه‌اندازی می‌کنیم تا فایل جدید struts-config.xml شناسایی شود، سپس به آدرس http://localhost:8080/strutspersonne/formulaire.do دسترسی پیدا می‌کنیم:

Image

فرم به‌درستی نمایش داده می‌شود. ممکن است کنجکاو باشیم ببینیم چگونه تگ‌های <html:XX> که در سراسر کد JSP فرم پخش شده‌اند، «ترجمه‌» شده‌اند:

<html>
    <meta http-equiv="pragma" content="no-cache"> 
    <head>
      <title>Personne - formulaire</title>
    <script language="javascript">
        function effacer(){
          with(document.frmPersonne){
            nom.value="";
          age.value="";
        }
      }
    </script>
  </head>

  <body>
      <center>

        <h2>Personne - formulaire</h2>
      <hr>
      <form name="frmPersonne" method="post" action="/strutspersonne/main.do">
          <table>
            <tr>
              <td>Nom</td>
            <td><input type="text" name="nom" size="20" value=""></td>
          </tr>

          <tr>
              <td>Age</td>
            <td><input type="text" name="age" size="3" value=""></td>
          </tr>
            <tr>
        </table>
        <table>
            <tr>

              <td><input type="submit" value="Envoyer"></td>
            <td><input type="reset" value="Rétablir"></td>
            <td><input type="button" name="btnEffacer" value="Effacer" onclick="effacer()"></td>
          </tr>
        </table>
      </form>
    </center>
  </body>
</html>

در فرم حاصل، دکمه‌های [Reset] و [Effacer] کار می‌کنند. دکمه ارسال [Envoyer] به URL /strutspersonne/main.do هدایت می‌کند. طبق فایل web.xml برنامه، کنترلر Struts این را مدیریت خواهد کرد. طبق فایل struts-config.html، کنترلر باید درخواست را به نمای /vues/main.html هدایت کند. بیایید امتحانش کنیم:

Image

همه چیز طبق انتظار کار می‌کند. اکنون باید مقادیر فرم را واقعاً پردازش کنیم، c.a.d. ما باید یک کلاس Action بنویسیم که داده‌های فرم را در یک شیء FormulaireBean دریافت کند.