Skip to content

4. Dinamik formların kullanımı

4.1. Dinamik formun tanımlanması

Struts'un, uygulamanın çeşitli servletleri tarafından işlenen HTML formlarının değerlerini depolamak için ActionForm nesnelerini kullandığını görmüştük. Uygulamamızdaki her form için, ActionForm sınıfından türetilmiş bir sınıf oluşturmamız gerekir. Bu işlem hızla oldukça zahmetli hale gelebilir; çünkü her xx alanı için setXx ve getXx adlı iki yöntem yazmamız gerekir. Struts bize,

  • kullanma imkanı sunar; bu formların yapısı, Struts ortamı tarafından bildirilen yapıya göre <form-beans> bölümünde yer alan struts-config.xml dosyasında
  • bölümünde tanımlanmış olan ve Struts ortamı tarafından belirtilen yapıya göre dinamik olarak oluşturulan formları kullanma imkânı sunar

Böylece, strutspersonne uygulamasının isim ve yaş değerlerini depolamak için kullanılan sınıf şu şekilde tanımlanabilir:

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

Formun her bir alanı için, iki özniteliğe sahip bir <form-property> etiketi tanımlanır:

  • name: alanın adı
  • type: Java türü

Bir web istemcisi tarafından gönderilen form değerleri karakter dizileri olduğundan, en yaygın kullanılan türler tek değerli alanlar için java.lang.String ve çok değerli alanlar için (aynı ada sahip onay kutuları, çoklu seçim listeleri vb.) java.lang.String[]'dir. DynactionForm sınıfı da ActionForm sınıfı gibi hiçbir işlem yapmayan bir validate yöntemine sahiptir. Form parametrelerinin geçerliliğini kontrol etmesini sağlamak için bu sınıftan türetme yapmalı ve validate yöntemini kendiniz yazmalısınız. Dolayısıyla formun tanımlaması şu şekilde olacaktır:

    <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 sınıfı tarafımızca yazılmalıdır.

4.2. Dinamik formla ilişkili DynaActionForm sınıfının yazılması

Yukarıda, istia.st.struts.personne.PersonneDynaForm sınıfını (ad, yaş) formuna bağladık. Şimdi bu sınıfı yazıyoruz:

package istia.st.struts.personne;

import javax.servlet.http.*;
import org.apache.struts.action.*;

public class PersonneDynaForm extends DynaActionForm {
   // doğrulama
  public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
    // hata yönetimi
    ActionErrors erreurs = new ActionErrors();
     // ad alanı boş olmamalı
    String nom = (String)this.get("nom");
    if (nom == null || nom.trim().equals("")) {
      erreurs.add("nomvide", new ActionError("personne.formulaire.nom.vide"));
    }
     // yaş alanı boş olmamalıdır
    String age = (String)this.get("age");
    if (age == null || age.trim().equals("")) {
      erreurs.add("agevide", new ActionError("personne.formulaire.age.vide"));
    }
    else {
      // yaş, pozitif bir tamsayı olmalıdır
      if (!age.matches("^\\s*\\d+\\s*$")) {
        erreurs.add("ageincorrect", new ActionError("personne.formulaire.age.incorrect", age));
        // hata listesi döndürülür
      }
    } //if
     // hata listesi döndürülür
    return erreurs;
  }
}//sınıf

Dikkat edilmesi gereken noktalar şunlardır:

  • sınıf, DynaActionForm sınıfından türetilmiştir
  • DynaActionForm sınıfının validate yöntemi yeniden yazılmıştır. Struts denetleyicisi tarafından çalıştırıldığında, PersonneDynaForm nesnesi oluşturulmuştur. Bu nesne, anahtarları formdaki "nom" ve "age" alanları, değerleri ise bu alanların değerleri olan bir sözlük içerir. DynaActionForm sınıfındaki yöntemler içinde bir alana erişmek için Object get(String nomDuChamp) yöntemi kullanılır. Bir alana değer atamak istendiğinde, void set(String nomDuChamp, Object değer) yöntemi kullanılabilir. Tam bir tanım için DynaActionForm sınıfının tanımına bakınız.
  • Formun nom ve age alanlarının değerleri alındıktan sonra, validate yöntemi, formun bir ActionForm nesnesine bağlandığında yazılan yöntemden farklı değildir.

4.3. Yeni FormulaireAction sınıfı

Yapılandırma dosyası, aşağıdaki /main eylemini tanımlar:

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

Bu tanım, strutspersonne uygulamasındakiyle aynıdır. /main eylemi, FormulaireAction türünde bir nesne tarafından gerçekleştirilir. Bu nesne, frmPersonne formundaki değerleri FormulaireBean türünde bir nesne içinde alırdı. Artık bu değerleri PersonneDynaForm türündeki bir nesneye alıyor. Dolayısıyla sınıfı yeniden yazmak gerekiyor:

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 {

     // Form geçerliyse, aksi takdirde bu noktaya gelemezdik
    PersonneDynaForm formulaire=(PersonneDynaForm)form;
    request.setAttribute("nom",formulaire.get("nom"));
    request.setAttribute("age",formulaire.get("age"));
    return mapping.findForward("reponse");
  }//işleme
}

Dikkat edilmesi gereken noktalar şunlardır:

  • Form verilerini içeren PersonneDynaForm sınıfını, tanımına erişebilmek için içe aktarmamız gerekir
  • execute yöntemi, [DynaActionForm].get yöntemi ile form parametrelerinin değerlerini alır.

strutspersonne uygulamasındaki FormulaireAction sınıfına gelince, yalnızca form değerlerine erişim şekli değişmiştir.

4.4. strutspersonne1 uygulamasının dağıtımı ve testi

4.4.1. Bağlamın oluşturulması

Bu yeni uygulamaya strutspersonne1 adını verdik. Tomcat'in <tomcat>\conf\serveur.xml dosyasında 4.x için yeni bir tanım oluşturuyoruz:

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

Bu işlem tamamlandıktan sonra Tomcat'i yeniden başlatmak gerekiyor. URL dosyasını çağırarak bağlamın geçerliliğini kontrol edebiliriz:

http://localhost:8080/strutspersonne1/

Image

4.4.2. Görünümler

strutspersonne uygulamasının "vues" klasörünü strutspersonne1 uygulamasının klasörüne kopyalayacağız. Zira görünümlerde herhangi bir değişiklik olmamıştır.

Image

4.4.3. Sınıfların derlenmesi

Oluşturmamız gereken iki sınıf var: PersonneDynaForm ve FormulaireAction; ikincisi, birincisini kullanıyor. Bunları bir JBuilder projesi yardımıyla oluşturabilir ve derleyebiliriz:

Image

4.4.4. WEB-INF klasörü

strutspersonne uygulamasındaki WEB-INF klasörünü strutspersonne1 uygulamasının klasörüne kopyalayacağız. Bazı dosyalar değişecek:

Image

struts-config.xml yapılandırma dosyası şu şekilde değişir:

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

Bu dosya, formun dinamik tanımı (çerçeveli kısım) dışında strutspersonne uygulamasındaki dosyayla aynıdır.

WEB-INF/classes klasörüne, JBuilder tarafından derlenen sınıflar yerleştirilecektir:

Image

WEB-INF\classes\ressources klasörüne mesaj dosyası yerleştirilir. Bu dosya değişmemiştir.

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. Testler

Testlere hazırız. Aşağıda, okuyucunun taklit etmesi istenen birkaç ekran görüntüsü bulunmaktadır.

URL http://localhost:8080/strutspersonne1/formulaire.do adresi isteniyor:

Image

Alanları doldurmadan [Envoyer] düğmesini kullanıyoruz:

Image

"age" alanında bir hata oluşacak şekilde işlemi tekrar yapalım:

Image

Aşağıdaki yanıtı alıyoruz:

Image

Bu sefer doğru değerleri girerek tekrar deniyoruz:

Image

Şu yanıtı alıyoruz:

Image

4.6. Sonuç

Dinamik formların kullanılması, form değerlerini depolamaktan sorumlu ActionForm türü sınıfların yazılmasını kolaylaştırır. Form yönetimini basitleştirme konusunda biraz daha ileri gidebiliriz. strutspersonne1 uygulamasında, formdaki değerlerin (ad, yaş) geçerliliğini kontrol etmek için PersonneDynaForm sınıfını oluşturduk. Uygulamada, bazı kontroller sık sık tekrarlanır: alanın boş olmaması, belirli bir düzenli ifadeyi kontrol eden alan, tamsayı alanı, tarih alanı vb. Bu tür standart doğrulamalar, struts-config.html yapılandırma dosyasında talep edilebilir. Yapılması gereken tüm doğrulamalar "standart" ise, form için ayrı bir sınıf yazmaya gerek kalmaz. Şimdi bunu inceleyeceğiz.