Skip to content

4. Використання динамічних форм

4.1. Оголошення динамічної форми

Ми бачили, що Struts використовує об’єкти ActionForm для зберігання значень форм HTML, які обробляються різними сервлетами додатка. Для кожної форми нашого додатка нам потрібно створити клас, похідний від ActionForm. Це може швидко стати досить обтяжливим, оскільки для кожного поля xx нам доводиться писати два методи: setXx та getXx. Struts надає нам можливість використовувати форми,

  • , структура яких оголошена у файлі struts-config.xml у розділі <form-beans>
  • і які динамічно створюються середовищем Struts відповідно до оголошеної структури

Таким чином, клас, що використовується для зберігання значень «ім’я» та «вік» у додатку 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

Оскільки значення форми, надіслані веб-клієнтом, є символьними рядками, найпоширенішими типами є 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));
        // повертається список помилок
      }
    } //if
     // повертається список помилок
    return erreurs;
  }
}//клас

Слід звернути увагу на наступне:

  • клас є похідним від DynaActionForm
  • метод validate класу DynaActionForm було переписано. Під час його виконання контролером Struts було створено об’єкт PersonneDynaForm. Він містить словник, ключами якого є поля форми «ім’я» та «вік», а значеннями — значення цих полів. Щоб отримати доступ до поля в методах класу DynaActionForm, використовується метод Object get(String nomDuChamp). Якщо потрібно присвоїти значення полю, можна скористатися методом void set(String nomDuChamp, Object значення). Повне визначення див. у описі класу DynaActionForm.
  • Після отримання значень полів «ім’я» та «вік» з форми метод validate не відрізняється від того, що був написаний, коли форма була пов’язана з об’єктом ActionForm.

4.3. Новий клас FormulaireAction

Файл конфігурації визначає таку дію /main:

...
    <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>\conf\serveur.xml сервера Tomcat 4.x:

    <Context path="/strutspersonne1" docBase="e:/data/serge/web/struts/personne1" />

Після цього потрібно перезапустити Tomcat. Перевірити правильність налаштування контексту можна, звернувшись до URL:

http://localhost:8080/strutspersonne1/

Image

4.4.2. Види

Скопіюємо папку «vues» з додатка strutspersonne в папку додатка strutspersonne1. Адже види не змінилися.

Image

4.4.3. Компіляція класів

Нам потрібно створити два класи: PersonneDynaForm та FormulaireAction, причому другий використовує перший. Їх можна створити та скомпілювати за допомогою проекту JBuilder:

Image

4.4.4. Папка WEB-INF

Скопіюємо папку WEB-INF з додатка strutspersonne у папку додатка strutspersonne1. Деякі файли зміняться:

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>
    <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:

Image

У папці WEB-INF\classes\ressources розміщується файл повідомлень. Він не змінився.

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>

Image

4.5. Тестування

Ми готові до тестів. Нижче наведено кілька знімків екрана, які читач може спробувати відтворити.

Потрібно виконати URL http://localhost:8080/strutspersonne1/formulaire.do:

Image

Використовуємо кнопку [Envoyer], не заповнюючи поля:

Image

Повторюємо спробу, але з помилкою у полі «age»:

Image

Отримуємо таку відповідь:

Image

Повторюємо спробу, цього разу вказавши правильні значення:

Image

Отримуємо таку відповідь:

Image

4.6. Висновок

Використання динамічних форм полегшує написання класів типу ActionForm, які відповідають за зберігання значень форм. Можна піти ще далі у спрощенні управління формами. У додатку strutspersonne1 ми створили клас PersonneDynaForm для перевірки правильності значень (ім’я, вік) у формі. На практиці деякі перевірки повторюються часто: поле не може бути порожнім, поле, що перевіряє певний регулярний вираз, цілочисельне поле, поле дати тощо. Такий тип стандартних перевірок можна задати у файлі конфігурації struts-config.html. Якщо всі необхідні перевірки є «стандартними», то для форми більше не потрібно писати окремий клас. Саме це ми й розглянемо зараз.