11. Örnek 09 - Tamsayıların dönüştürülmesi ve doğrulanması
Şimdi, bir formdaki parametrelerin dönüştürülmesi ve doğrulanmasına ilişkin bir dizi örneği ele alacağız. Sorun şudur: [http://machine:port/.../Action] biçimindeki bir URL'i işlemek için, [FilterDispatcher] denetleyicisi, istenen eylemi uygulayan sınıfı örneklendirir ve bu sınıfın yöntemlerinden birini, varsayılan olarak execute adlı yöntemi çalıştırır. Bu execute yöntemine yapılan çağrı, bir dizi ara alıcıdan geçer:
![]() |
Yönlendiricilerin listesi, [struts2-core.jar] arşivinin kök dizininde bulunan [struts-default.xml] dosyasında tanımlanmıştır. Bu dosyada tanımlanan yönlendiricilerin listesi şöyledir:
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
Yönlendiriciler arasında, isteğe parami=valeuri biçiminde eşlik eden parami parametrelerinin değerlerini valeuri olarak eyleme ekleme görevini üstlenen bir yönlendirici bulunmaktadır. valeuri değerinin, varsa setParami yöntemi aracılığıyla eylemin parami alanına enjekte edileceği bilinmektedir. Aksi takdirde, herhangi bir enjeksiyon gerçekleşmez ve hata bildirilmez.
parami=valeuri dizesi bir karakter dizisidir. Şimdiye kadar, valeuri, String türündeki parami alanlarına enjekte edilmiştir:
valeuri dizesinin, parami dizesinin değeri olarak enjekte edilmesi herhangi bir sorun yaratmamıştır. Eğer parami, String türünde değilse, o zaman valeuri, parami'ten Ti türüne dönüştürülmelidir. İşte dönüştürmeyle ilgili sorun da budur. Örneğin, bir yaşın tam sayı olmasını istersek, eylemde şöyle yazarız:
Ayrıca, yaşın 1 ile 150 arasında sınırlandırılmasını isteyebiliriz. Burada bir geçerlilik sorunu söz konusudur. parami parametresi, geçerli olmasa bile doğru türe dönüştürülebilir. Dolayısıyla aşılması gereken iki adım vardır. Bir isteğin işlenme şemasına geri dönersek:
![]() |
İki interceptor, sırasıyla parametrelerin dönüştürülmesi ve geçerliliğinin kontrol edilmesinden sorumlu olacaktır. Adımlardan biri başarısız olursa, istek eyleme doğru ilerlemez (yukarıdaki kırmızı akış şeması). Hatalı parametrelerin gönderildiği form, hata mesajlarıyla birlikte yeniden görüntülenir.
Parametrelerin dönüştürülmesi ve doğrulanmasıyla ilgili interceptörler, daha önce sunulan interceptör listesinin 19. ve 20. satırlarında yer alan conversionError ve validation interceptörleridir. 20-22. satırlarda, çağrılan yöntem input, back, cancel veya browse yöntemlerinden biriyse validation interceptörünün uygulanmadığına dikkat edilmelidir. Bu özelliğini ilerleyen bölümlerde kullanacağız.
Öncelikle tamsayıların dönüştürülmesi ve doğrulanmasını inceleyeceğiz. Doğrulama işlemi birçok unsuru içerdiğinden, bu ilk örnek üzerinde biraz zaman harcayacağız. Bunları öğrendikten sonra, sonraki örnekleri daha hızlı ele alacağız.
11.1. Form
![]() |
- 'den [1]'e, giriş formu
- [2], değer girmeden doğrulama yapıldığında elde edilen sonuç
11.2. NetBeans projesi
NetBeans projesi şu şekildedir:
![]() |
- [1]'te, uygulamanın üç görünümü
- [2] dosyasında, kaynak kodlar, uluslararasılaştırılmış mesaj dosyaları ve Struts yapılandırma dosyaları.
11.3. Struts yapılandırması
Uygulama, [struts.xml] ve [example.xml] dosyalarıyla yapılandırılır.
[struts.xml] dosyası şu şekildedir:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.custom.i18n.resources" value="messages" />
<include file="example/example.xml"/>
<package name="default" namespace="/" extends="struts-default">
<default-action-ref name="index" />
<action name="index">
<result type="redirectAction">
<param name="actionName">Accueil</param>
<param name="namespace">/example</param>
</result>
</action>
</package>
</struts>
12-18. satırlar, kullanıcı herhangi bir eylem belirtmediğinde [/example/Accueil] eylemini varsayılan eylem olarak tanımlar.
[example.xml] dosyası şöyledir:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="example" namespace="/example" extends="struts-default">
<action name="Accueil">
<result name="success">/example/Accueil.JSP</result>
</action>
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.JSP</result>
<result name="cancel" type="redirect">/example/Accueil.JSP</result>
<result name="success">/example/ConfirmationFormInt.JSP</result>
</action>
</package>
</struts>
- 8-10. satırlar: [Accueil] eylemi, [Accueil.JSP] görünümünü görüntüler
- 11. satır: [FormInt] eylemi, varsayılan olarak [example.FormInt] sınıfının execute yöntemini çalıştırır. Göreceğiz ki, input ve cancel adlı iki yöntem daha çalıştırılacaktır. Bu yöntemler, sorgu parametrelerinde belirtilecektir.
- 12. satır: input anahtarı, [FormInt.JSP] görünümünü (5. satır) görüntüleyecektir. Bu görünüm, formun görünümüdür.
- 13. satır: cancel anahtarı, [Annuler] bağlantısıyla ilişkili cancel yöntemi tarafından döndürülecektir. Yönlendirme (type=redirect) sonrasında görüntülenen görünüm [Accueil.JSP] olacaktır.
- 14. satır: success anahtarı, [FormInt] eyleminin execute yöntemi tarafından döndürülür. İstek execute yöntemine ulaşırsa, bu, isteğin tüm ara alıcıları, özellikle de parametrelerin geçerliliğini kontrol edenleri başarıyla geçtiği anlamına gelir. execute yöntemi ise, success anahtarını döndürmekle yetinir; bu anahtar, [ConfirmationInt.JSP] onay görünümünü görüntüleyecektir.
11.4. Mesaj dosyaları
[messages.properties] dosyası şu şekildedir:
Accueil.titre=Accueil
Accueil.message=Struts 2 - Conversions et validations
Accueil.FormInt=Saisie de nombres entiers
Form.titre=Conversions et validations
FormInt.message=Struts 2 - Conversion et validation de nombres entiers
Form.submitText=Valider
Form.cancelText=Annuler
Form.clearModel=Raz mod\u00e8le
Confirmation.titre=Confirmation
Confirmation.message=Confirmation des valeurs saisies
Confirmation.champ=champ
Confirmation.valeur=valeur
Confirmation.lien=Formulaire de test
Bu dosyaya ek olarak, görünümler aşağıdaki [FormInt.properties] dosyasını kullanır:
int1.prompt=1-Nombre entier positif de deux chiffres
int1.error=Tapez un nombre entier positif de deux chiffres
int2.prompt=2-Nombre entier
int2.error=Tapez un nombre entier
int3.prompt=3-Nombre entier >=-1
int3.error=Tapez un nombre entier >=-1
int4.prompt=4-Nombre entier <=10
int4.error=Tapez un nombre entier <=10
int5.prompt=5-Nombre entier dans l''intervalle [1,10]
int5.error=Tapez un nombre entier dans l''intervalle [1,10]
int6.prompt=6-Nombre entier dans l''intervalle [2,20]
int6.error=Tapez un nombre entier dans l''intervalle [2,20]
[FormInt.properties] dosyası, yalnızca görünümü oluşturan eylem [FormInt] eylemi olduğunda kullanılır. Bu, mesaj dosyası çok büyükse dosyayı bölümlere ayırmanın bir yoludur. [Action.properties] dosyasında Action eyleminin mesajları uluslararası hale getirilir.
11.5. Görünümler ve eylemler
Şimdi uygulamanın görünümlerini ve eylemlerini tanıtacağız. Uygulamanın yapılandırmasına göre:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="example" namespace="/example" extends="struts-default">
<action name="Accueil">
<result name="success">/example/Accueil.JSP</result>
</action>
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.JSP</result>
<result name="cancel" type="redirect">/example/Accueil.JSP</result>
<result name="success">/example/ConfirmationFormInt.JSP</result>
</action>
</package>
</struts>
görüldüğü üzere, üç adet [Accueil.JSP, FormInt.JSP, ConfirmationFormInt.JSP] görünümü ve iki adet [Accueil, FormInt] eylemi bulunmaktadır.
11.5.1. Accueil.JSP
[Accueil.JSP] görünümü şu şekildedir:
![]() |
Kodu şöyledir:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title><s:text name="Accueil.titre"/></title>
<s:head/>
</head>
<body background="<s:url value="/ressources/standard.jpg"/>">
<h2><s:text name="Accueil.message"/></h2>
<ul>
<li>
<s:url id="URL" action="FormInt!input"/>
<s:a href="%{URL}"><s:text name="Accueil.FormInt"/></s:a>
</li>
</ul>
</body>
</html>
- satırdaki bağlantı şu HTML kodunu oluşturur:
<a href="<a href="view-source:http://localhost:8084/exemple-09/example/FormInt.action">/exemple-09/example/FormInt!input.action</a>">Saisie de nombres entiers</a>
Dolayısıyla bu, [example.xml]'te aşağıdaki gibi yapılandırılmış olan [FormInt] eylemine yönlendiren bir bağlantıdır:
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.JSP</result>
<result name="cancel" type="redirect">/example/Accueil.JSP</result>
<result name="success">/example/ConfirmationFormInt.JSP</result>
</action>
Bağlantıya tıklandığında, [example.FormInt] sınıfı örneklenecek ve bu sınıfın input yöntemi çalıştırılacaktır. Bu yöntem mevcut olmadığı için, üst sınıf olan ActionSupport'in input yöntemi çalıştırılacaktır. Bu yöntem, input anahtarını döndürmekten başka bir şey yapmaz. Dolayısıyla, [/example/FormInt.JSP] görünümü görüntülenecektir.
Ayrıca, input yöntemi, doğrulama engelleyicisi tarafından göz ardı edilen yöntemlerden biridir:
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
Bu nedenle parametre doğrulaması yapılmayacaktır. Bu önemlidir, çünkü burada parametre yoktur ve daha sonra göreceğimiz üzere doğrulama kuralları altı parametrenin varlığını zorunlu kılacaktır.
11.5.2. [FormInt] eylemi
[FormInt] eylemi, aşağıdaki [FormInt] sınıfıyla ilişkilidir:
package example;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.interceptor.validation.SkipValidation;
public class FormInt extends ActionSupport implements ModelDriven, SessionAware {
// parametresiz oluşturucu
public FormInt() {
}
// eylem modeli
public Object getModel() {
if (session.get("model") == null) {
session.put("model", new FormIntModel());
}
return session.get("model");
}
public String cancel() {
// modeli temizliyoruz
((FormIntModel) getModel()).clearModel();
// sonuç
return "cancel";
}
@SkipValidation
public String clearModel() {
// modeli sıfırlama
((FormIntModel) getModel()).clearModel();
// sonuç
return INPUT;
}
// SessionAware
private Map<String, Object> session;
public void setSession(Map<String, Object> session) {
this.session = session;
}
// doğrulama
@Override
public void validate() {
// int6 girişi geçerli mi?
if (getFieldErrors().get("int6") == null) {
int int6 = Integer.parseInt(((FormIntModel) getModel()).getInt6());
if (int6 < 2 || int6 > 20) {
addFieldError("int6", getText("int6.error"));
}
}
}
}
Bu kodu ihtiyaç duyuldukça yorumlayacağız. Şimdilik:
- 9. satırda, [FormInt] sınıfı iki arayüzü uygulamaktadır:
- Tek bir yöntemi olan ModelDriven ve 16. satırdaki getModel
- SessionAware, tek bir yönteme sahiptir; 41. satırdaki setSession
- 16-21. satırlar: ModelDriven arayüzünün uygulanması. Bu arayüzün, bir görünümün modelini harici bir sınıfa, bu örnekte aşağıdaki [FormIntModel] sınıfına aktarmaya olanak sağladığını hatırlatmak isteriz:
package example;
public class FormIntModel {
// parametresiz oluşturucu
public FormIntModel() {
}
// form alanları
private String int1;
private Integer int2;
private Integer int3;
private Integer int4;
private Integer int5;
private String int6;
// şablon sıfırlama
public void clearModel(){
int1=null;
int2=null;
int3=null;
int4=null;
int5=null;
int6=null;
}
// getter ve setter'lar
...
}
[FormIntModel] modeli, [FormInt.JSP] görünümündeki altı giriş alanına karşılık gelen altı alana sahiptir. Gönderilen değerler bu altı alana aktarılacaktır. Bunlardan dördü Integer türündedir. Dolayısıyla bu alanlar için String --> Integer dönüşümü sorunu ortaya çıkacaktır. clearModel yöntemi, şablonu sıfırlamaya olanak tanır.
[FormInt] eyleminin getModel yöntemine geri dönelim:
// eylem modeli
public Object getModel() {
if (session.get("model") == null) {
session.put("model", new FormIntModel());
}
return session.get("model");
}
- 3-5. satırlar: Şablon oturumda aranır. Eğer bulunmazsa, şablonun bir örneği oluşturulur ve oturuma eklenir.
- 6. satır: Eyleme yapılan her yeni istekle birlikte eylemin bir örneği oluşturulsa da, model oturumda kalmaya devam eder.
Sınıfın input adlı bir yöntemi tanımlamadığını görüyoruz, ancak üst sınıfta input anahtarını döndüren bir yöntem bulunmaktadır. Bu yöntemin çalıştırılması, şimdi sunacağımız [FormInt.JSP] görünümünün görüntülenmesine yol açar.
11.5.3. [FormInt.JSP] görünümü
[FormInt.JSP] görünümü şu şekildedir:
![]() |
- [1]'te, boş form
- [2]'te, hatalı parametrelerin doğrulanmasından sonraki form.
Kodu şu şekildedir:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title><s:text name="Form.titre"/></title>
<s:head/>
</head>
<body background="<s:url value="/ressources/standard.jpg"/>">
<h2><s:text name="FormInt.message"/></h2>
<s:form name="formulaire" action="FormInt">
<s:textfield name="int1" key="int1.prompt"/>
<s:textfield name="int2" key="int2.prompt"/>
<s:textfield name="int3" key="int3.prompt"/>
<s:textfield name="int4" key="int4.prompt"/>
<s:textfield name="int5" key="int5.prompt"/>
<s:textfield name="int6" key="int6.prompt"/>
<s:submit key="Form.submitText" method="execute"/>
</s:form>
<br/>
<s:url id="URL" action="FormInt" method="cancel"/>
<s:a href="%{URL}"><s:text name="Form.cancelText"/></s:a>
<br/>
<s:url id="URL" action="FormInt" method="clearModel"/>
<s:a href="%{URL}"><s:text name="Form.clearModel"/></s:a>
</body>
</html>
- 12-17. satırlar: [FormIntModel] şablonundaki altı alana karşılık gelen altı giriş alanı, [FormInt] eylemi. Görünüm görüntülendiğinde, bu alanlar tarafından görüntülenen değer için giriş alanlarının value öznitelikleri kullanılır. value özniteliği yoksa, name özniteliği kullanılır.
- 12. satır: Eylem, ModelDriven arayüzünü uyguluyorsa, giriş alanı (name), eylemin veya eylemin şablonunun int1 alanıyla ilişkilendirilir. Burada durum böyledir. Bu, diğer tüm alanlar için de geçerlidir.
- 18. satır: [Valider] düğmesi, girişleri 11. satırda tanımlanan [FormInt] eylemine gönderir. Bu eylemin execute yöntemi çalıştırılacaktır.
- 21-22. satırlar: [Annuler] bağlantısı, [FormInt.cancel] yöntemini yürütür.
- 24-25. satırlar: [Raz modèle] bağlantısı, [FormInt.clearModel] yöntemini çalıştırır.
11.5.4. [ConfirmationFormInt.JSP] görünümü
![]() |
[FormInt.JSP] formundaki tüm girdiler geçerli olduğunda görüntülenir.
- [1]'te, geçerli değerler
- [2]'te onay sayfası
[ConfirmationInt.JSP] görünümünün kodu şöyledir:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title><s:text name="Confirmation.titre"/></title>
<s:head/>
</head>
<body background="<s:url value="/ressources/standard.jpg"/>">
<h2><s:text name="Confirmation.message"/></h2>
<table border="1">
<tr>
<th><s:text name="Confirmation.champ"/></th>
<th><s:text name="Confirmation.valeur"/></th>
</tr>
<tr>
<td><s:text name="int1.prompt"/></td>
<td><s:property value="int1"/></td>
</tr>
<tr>
<td><s:text name="int2.prompt"/></td>
<td><s:property value="int2"/></td>
</tr>
<tr>
<td><s:text name="int3.prompt"/></td>
<td><s:property value="int3"/></td>
</tr>
<tr>
<td><s:text name="int4.prompt"/></td>
<td><s:property value="int4"/></td>
</tr>
<tr>
<td><s:text name="int5.prompt"/></td>
<td><s:property value="int5"/></td>
</tr>
<tr>
<td><s:text name="int6.prompt"/></td>
<td><s:property value="int6"/></td>
</tr>
</table>
<br/>
<s:url id="URL" action="FormInt" method="input"/>
<s:a href="%{URL}"><s:text name="Confirmation.lien"/></s:a>
</body>
</html>
Bu kodu anlamak için, görünümün [FormInt] sınıfının örneklendirilmesinden sonra görüntülendiğini hatırlamak gerekir. Dolayısıyla, bu sınıfın ve modeli olan [FormIntModel]'in alanlarına görünümden erişilebilir.
- 16-38. satırlar: Altı alanın değerleri görüntülenir
- 42-43. satırlar: [FormInt] eylemine bir bağlantı. Bu bağlantı için oluşturulan kod şöyledir:
<a href="/exemple-09/example/FormInt!input.action">Formulaire de test</a>
Bağlantıdaki URL kodu, [FormInt] eyleminin input yönteminin bu isteği işlemesi gerektiğini belirtir. [FormInt] eyleminin [example.xml] içindeki yapılandırmasını hatırlayalım:
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.JSP</result>
<result name="cancel" type="redirect">/example/Accueil.JSP</result>
<result name="success">/example/ConfirmationFormInt.JSP</result>
</action>
[FormInt] sınıfındaki input yöntemi, üst sınıfı olan ActionSupport sınıfındaki yöntemle aynı olacaktır. [FormInt] sınıfının input yöntemi, aşağıdaki yakalayıcıların çalıştırılmasından sonra yürütülür:
![]() |
input yöntemine yapılan çağrının, doğrulama ara sınıfı tarafından göz ardı edildiği bilinmektedir. Dolayısıyla herhangi bir doğrulama yapılmayacaktır.
[FormInt.JSP] görünümü görüntülenir:
![]() |
[2]'te, giriş alanları girilen değerlere geri döner. Bu normal görünebilir, ancak öyle değildir. [FormInt] eylemi çağrıldığından, ilişkili [FormInt] sınıfı örneklendi. Bu sınıf, ModelDriven arayüzünü uyguladığından, getModel yöntemi çağrıldı:
// eylem modeli
public Object getModel() {
if (session.get("model") == null) {
session.put("model", new FormIntModel());
}
return session.get("model");
}
Eylem modelinin oturumdan alındığı görülüyor. Bir önceki adımda bu model, gönderilen değerlerle güncellenmişti. Dolayısıyla bu değerler yeniden kullanılıyor. Modeli oturuma kaydetmemiş olsaydık, [FormInt.JSP] görünümünde altı boş alan olurdu.
11.5.5. [FormInt!clearModel] eylemi
[Formint!clearModel] eylemi, [Raz modèle] bağlantısına tıklanmasıyla tetiklenir:
![]() |
- [1]'e, hatalı giriş yapıldıktan sonra form
- [2]'e, [Raz modèle] bağlantısına tıklandıktan sonra form.
[FormInt.clearModel] yöntemi şu şekildedir:
@SkipValidation
public String clearModel() {
// model sıfırlama
((FormIntModel) getModel()).clearModel();
// sonuç
return INPUT;
}
- 1. satır: Yapılacak bir doğrulama yoktur. Bunu belirtmek için @SkipValidation notasyonu kullanılır. Doğrulama engelleyicisi bu durumda doğrulamaları yapmayacaktır.
- 4. satır: [FormIntModel].clearModel yöntemi yürütülür. Bu yönteme daha önce rastlamıştık. Bu yöntem, modelin altı alanını null değerine sıfırlar.
- 7. satır: Yöntem, input anahtarını döndürür.
[FormInt] eyleminin yapılandırmasına geri dönersek:
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.JSP</result>
<result name="cancel" type="redirect">/example/Accueil.JSP</result>
<result name="success">/example/ConfirmationFormInt.JSP</result>
</action>
görüldüğü gibi, input anahtarı, [FormInt.JSP] görünümünü görüntüleyecektir. Bu görünüm, modelin altı alanını gösterir. Bu alanlar null'te yer aldığından, görünüm altı boş alan ([2]) görüntüler.
11.5.6. [FormInt!cancel] eylemi
[Formint!cancel] eylemi, [Annuler] bağlantısına tıklanmasıyla tetiklenir:
![]() |
- [1]'e, hatalı girişin ardından form
- [2]'e, [Annuler] bağlantısına tıklandıktan sonra ana sayfaya yönlendirilir.
[FormInt.cancel] yöntemi şu şekildedir:
public String cancel() {
// modeli temizliyoruz
((FormIntModel) getModel()).clearModel();
// sonuç
return "cancel";
}
- 1. satır: Yöntemin başında SkipValidation notu bulunmadığına dikkat edilmelidir. Oysa biz doğrulamaları yapmak istemiyoruz. cancel yöntemi, input, back, cancel ve browse yöntemlerinden biridir; bu yöntemler doğrulama engelleyicisi tarafından göz ardı edildiğinden, SkipValidation etiketine de gerek yoktur.
- 3. satır: şablonu boşaltır
- 5. satır: cancel anahtarını döndürür
[FormInt] eyleminin yapılandırmasına geri dönersek:
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.JSP</result>
<result name="cancel" type="redirect">/example/Accueil.JSP</result>
<result name="success">/example/ConfirmationFormInt.JSP</result>
</action>
cancel anahtarının, istemcinin yönlendirilmesinden sonra [Accueil.JSP] görünümünü görüntüleyeceği görülür. [2] görünümü bunu göstermektedir.
11.6. Doğrulama süreci
Şimdi, şablondaki aşağıdaki altı alanla ilişkili altı giriş alanının doğrulanmasına geçiyoruz:
// form alanları
private String int1;
private Integer int2;
private Integer int3;
private Integer int4;
private Integer int5;
private String int6;
Bu doğrulama, [FormInt] sınıfı her örneklendiğinde ve yürütülen yöntem doğrulama engelleyicisi tarafından atlanmadığında gerçekleşir. Bu işlem şu dosya tarafından yönetilir:
- [FormInt-validation.xml] dosyası (eğer [FormInt] sınıfıyla aynı klasörde bulunuyorsa)
- [FormInt.validate] yöntemi (varsa).
![]() |
- [1]'te: doğrulama işlemi için gerekli olan [xwork-validator-1.0.2.dtd] dosyası
- [2] dosyasına: [FormInt-validation.xml] dosyası, [FormInt] sınıfıyla aynı klasörde
[FormInt-validation.xml] dosyası şöyledir:
<!--
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//
EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
-->
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//
EN" "http://localhost:8084/örnek-09/example/xwork-validator-1.0.2.dtd">
<validators>
<field name="int1" >
<field-validator type="requiredstring" short-circuit="true">
<message key="int1.error"/>
</field-validator>
<field-validator type="regex" short-circuit="true">
<param name="expression">^\d{2}$</param>
<param name="trim">true</param>
<message key="int1.error"/>
</field-validator>
</field>
<field name="int2" >
...
</field>
...
</validators>
- [3] dosyasında, doğrulama dosyasının DTD (Belge Türü Tanımı) dosyasındaki URL dosyası bulunur. Bu dosyaya erişim sağlanabilmelidir, aksi takdirde doğrulama dosyası kullanılmaz.
- [7] dosyasını, uygulama tarafından kullanılan DTD dosyasının URL dosyasına dönüştürün. İnternet erişimi olmasa bile bu dosyaya sahip olabilmek için exemple-09 [1] projesinin [example] klasörüne DTD dosyasını yerleştirdik.
- 11-20. satırlar: Şablondaki int1 alanıyla ilişkili int1 parametresinin doğrulama koşullarını belirler.
Formda int1 olarak adlandırılan etiket şöyledir:
<s:textfield name="int1" key="int1.prompt" />
Şablondaki int1 alanı şu şekilde tanımlanmıştır:
private String int1;
- 12-14. satırlar: int1 parametresinin mevcut olup olmadığını (null değil) ve uzunluğunun sıfırdan farklı olup olmadığını kontrol eder. Aksi takdirde, giriş alanına bir hata mesajı eklenir. [FormInt.properties]'te şu şekilde tanımlanmıştır:
int1.error=Tapez un nombre entier positif de deux chiffres
Hata olması durumunda, int1 parametresinin doğrulama işlemi durdurulur (short-circuit=true).
- 15-19. satırlar: int1 parametresinin geçerliliği bir düzenli ifade ile kontrol edilir.
- 16. satır: Düzenli ifade; burada, başında ve sonunda hiçbir şey olmayan 2 rakamdır.
- 17. satır: int1 parametresi, düzenli ifadeyle karşılaştırılmadan önce başındaki ve sonundaki boşluklardan arındırılır.
- 18. satır: Olası hata mesajı. Bu, önceki doğrulayıcıdakiyle aynıdır.
Şimdi nasıl çalıştığına bir bakalım:
![]() |
- [1]'e dönüştürülür; int1 alanı için hatalı bir giriş
- [2]'te, geri gönderilen sayfa:
- int1.error anahtarına ait hata mesajı görünüyor. Kırmızı renkte.
- Hatalı alanın başlığı da kırmızı renktedir.
- Hatalı giriş yeniden görüntülenir. Bu, varsayılan davranış olmayabileceğinden önceden dikkate alınmalıdır.
Formun doğrulanmasının, istek tüm ara alıcıları, özellikle de doğrulama ara alıcısını geçmeyi başarırsa, [FormInt].execute yönteminin çalıştırılmasına neden olduğunu gördük:
![]() |
- istek, eylemin execute yöntemine ulaşırsa, bu yöntem daha önce gördüğümüz gibi success anahtarını denetleyiciye geri gönderir.
- eğer doğrulama interceptörü, test edilen parametrelerin geçersiz olması nedeniyle isteği durdurursa, o zaman input anahtarı denetleyiciye geri gönderilir.
[FormInt] eylemi şu şekilde yapılandırıldığından:
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.JSP</result>
<result name="cancel" type="redirect">/example/Accueil.JSP</result>
<result name="success">/example/ConfirmationFormInt.JSP</result>
</action>
bir doğrulama hatası olduğunda, [FormInt.JSP] görünümü, yani form görüntülenir. Struts etiketleri, kendilerine eklenmiş olası hata mesajlarını gösterecek şekilde tasarlanmıştır. Dolayısıyla, farklı alanlara eklenmiş hata mesajlarını içeren [FormInt.JSP] görünümü elde edilir. [2] görünümü de bunu göstermektedir.
Şimdi, modelde aşağıdaki gibi tanımlanan int2 alanının doğrulamasını inceleyelim:
private Integer int2;
[FormInt-validation.xml]'teki int2 alanının doğrulama kuralları şu şekildedir:
<field name="int2" >
<field-validator type="required" short-circuit="true">
<message key="int2.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="int2.error"/>
</field-validator>
</field>
- 2-4. satırlar: int2 parametresinin mevcut olup olmadığını kontrol eder.
- 5-7. satırlar: String --> Integer dönüşümünün mümkün olup olmadığını kontrol eder
- 3. ve 6. satırlar: int2.error anahtarının hata mesajı şöyledir:
int2.error=Tapez un nombre entier
[FormInt-validation.xml]'teki şablonun Integer ve int3 alanlarının doğrulaması şu şekildedir:
<field name="int3" >
<field-validator type="required" short-circuit="true">
<message key="int3.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="int2.error"/>
</field-validator>
<field-validator type="int" short-circuit="true">
<param name="min">-1</param>
<message key="int3.error"/>
</field-validator>
</field>
- 8-11. satırlar: int3 alanının >=-1 tamsayı türü olduğunu doğrular
- 3. ve 7. satırlar: int3.error anahtarına ilişkin hata mesajı şöyledir:
int3.error=Tapez un nombre entier >=-1
[FormInt-validation.xml]'teki şablonun Integer ve int4 alanlarının doğrulaması şu şekildedir:
<field name="int4" >
<field-validator type="required" short-circuit="true">
<message key="int4.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="int2.error"/>
</field-validator>
<field-validator type="int" short-circuit="true">
<param name="max">10</param>
<message key="int4.error"/>
</field-validator>
</field>
- 8-11. satırlar: değerin <=10 tamsayı türünde olduğunu kontrol eder
- 3. ve 7. satırlar: int4.error anahtarına ilişkin hata mesajı şöyledir:
int4.error=Tapez un nombre entier <=10
Şablondaki Integer int5 alanının [FormInt-validation.xml]'te doğrulanması şu şekildedir:
<field name="int5" >
<field-validator type="required" short-circuit="true">
<message key="int5.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="int2.error"/>
</field-validator>
<field-validator type="int" short-circuit="true">
<param name="min">1</param>
<param name="max">10</param>
<message key="int5.error"/>
</field-validator>
</field>
- 5-9. satırlar: Değerin [1, 10] aralığında bir tamsayı olup olmadığını kontrol eder.
- 3. ve 8. satırlar: int5.error anahtarına ilişkin hata mesajı şöyledir:
int5.error=Tapez un nombre entier dans l''intervalle [1,10]
[FormInt-validation.xml]'teki şablonun String ve int6 alanlarının doğrulaması şu şekildedir:
<field name="int6" >
<field-validator type="requiredstring" short-circuit="true">
<message key="int6.error"/>
</field-validator>
<field-validator type="regex" short-circuit="true">
<param name="expression">^\d{1,2}$</param>
<param name="trim">true</param>
<message key="int6.error"/>
</field-validator>
</field>
- 5-9. satırlar: int6'in 2 basamaklı bir dize olup olmadığını kontrol eder.
- 3. satır, 8: int6.error anahtarına ait hata mesajı şöyledir:
int6.error=Tapez un nombre entier dans l''intervalle [2,20]
Önceki doğrulama, int6 parametresinin [2,20] aralığında bir tamsayı olup olmadığını kontrol etmemektedir. Bu doğrulama, [FormInt-validation.xml] dosyası işlendikten sonra yürütülen [FormInt].validate yönteminde yapılır. Bu yöntem şöyledir:
// doğrulama
@Override
public void validate() {
// int6 girişi geçerli mi?
if (getFieldErrors().get("int6") == null) {
int int6 = Integer.parseInt(((FormIntModel) getModel()).getInt6());
if (int6 < 2 || int6 > 20) {
addFieldError("int6", getText("int6.error"));
}
}
}
- 5. satır: int6 alanına ilişkin herhangi bir hata olup olmadığına bakılır. Varsa, işlem devam etmez.
- 6. satır: Hata yoksa, şablondaki String int6 alanı alınır ve tamsayıya dönüştürülür.
- 7. satır: Alınan tamsayının [2,20] aralığında olup olmadığı kontrol edilir.
- 8. satır: Eğer değilse, int6 alanına bir hata mesajı eklenir. Bu hata mesajı, int6.error anahtarıyla mesaj dosyasında aranır.
Bu doğrulama sürecinin sonunda hatalar varsa, [FormInt].execute yöntemine yapılan çağrı kesilir ve input anahtarı Struts denetleyicisine iade edilir.
![]() |
11.7. Son ayrıntılar
Tamsayıları girmenin çeşitli yollarını gördük. Bunların hepsi birbirine eşdeğer değildir. Örneğin, int5 ve int6 giriş alanlarını ele alalım:
[FormInt.JSP] görünümünde, bu alanlar şu şekilde tanımlanmıştır:
<s:textfield name="int5" key="int5.prompt"/>
<s:textfield name="int6" key="int6.prompt"/>
Şablonları ise [FormIntModel.java]'te tanımlanmıştır:
private Integer int5;
private String int6;
int5 alanı Integer türündeyken, int6 alanı String türündedir. Doğrulama kuralları farklıdır:
<field name="int5" >
<field-validator type="required" short-circuit="true">
<message key="int5.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="int2.error"/>
</field-validator>
<field-validator type="int" short-circuit="true">
<param name="min">1</param>
<param name="max">10</param>
<message key="int5.error"/>
</field-validator>
</field>
<field name="int6" >
<field-validator type="requiredstring" short-circuit="true">
<message key="int6.error"/>
</field-validator>
<field-validator type="regex" short-circuit="true">
<param name="expression">^\d{1,2}$</param>
<param name="trim">true</param>
<message key="int6.error"/>
</field-validator>
</field>
int6 alanının doğrulaması, [FormInt] eyleminin validate yöntemi ile tamamlanır:
public void validate() {
// int6 girişi geçerli mi?
if (getFieldErrors().get("int6") == null) {
int int6 = Integer.parseInt(((FormIntModel) getModel()).getInt6());
if (int6 < 2 || int6 > 20) {
addFieldError("int6", getText("int6.error"));
}
}
Doğrulama kuralları, farklı şekilde ifade edilse de, her ikisi de girilen alanın belirli bir aralıkta yer alan bir tamsayı olup olmadığını kontrol etmeyi amaçlamaktadır. Ancak, aşağıdaki ekran görüntülerinde de görüldüğü gibi, int5 ve int6 alanlarının çalışma sırasındaki davranışları farklıdır:
![]() |
- [1]'te, her iki alan için de aynı hatalı giriş
- [2]'te, geri gönderilen hata sayfası. Her iki alanın da farklı hata mesajları vardır.
- [3]'te, int5 alanı için istenmeyen bir mesaj görünüyor, çünkü bu mesaj İngilizce. Bu, String --> Integer dönüşümünün başarısız olmasından kaynaklanıyor. Ayrıca Apache günlüklerinde bir istisna var:
Oldukça ilginç bir şekilde, Struts, bulamadığı bir FormIntModel.setInt5(String value) yöntemini aramıştır.
Hata mesajının anahtarı xwork.default.invalid.fieldvalue'tir. Bunu Fransızca'ya çevirmek için, bu anahtara Fransızca bir metin atamak yeterlidir. Böylece [messages.properties] dosyasına şu satırı ekliyoruz:
...
xwork.default.invalid.fieldvalue=Valeur invalide pour le champ "{0}".
11.8. Conclusion
Parametre doğrulamalarına yönelik bu ilk uygulamanın incelemesi burada sona eriyor. Açıklaması oldukça karmaşıktı. Şimdi benzer uygulamaları inceleyeceğiz. Bu nedenle, yalnızca değişen kısımları ele alacağız.















