14. Örnek 11 – Tarih Dönüştürme ve Doğrulama
Yeni uygulamada tarih girişi şu şekildedir:
![]() |
- [1]'te, giriş formu
- [2], geri gönderilen yanıt
Uygulama, tamsayı girişiyle benzer şekilde çalışır; bu nedenle sadece farklı olan noktalara değineceğiz.
14.1. NetBeans projesi
NetBeans projesi şu şekildedir:
![]() |
- [1]'te, uygulamanın görünümleri
- [Accueil.JSP]: ana sayfa
- [FormDate.JSP]: giriş formu
- [ConfirmationFormDate.JSP]: onay sayfası
- [2]'e, mesaj dosyası [messages.properties]'e ve Struts'un ana yapılandırma dosyası
- [3]'te:
- [FormDate.java]: Formu görüntüleyen ve işleyen eylem
- [FormDate-validation.xml]: [FormDate] eyleminin doğrulama kuralları. Bu dosya, bu doğrulamaları modele devreder.
- [FormDateModel]: [FormDate] eyleminin modeli
- [ FormDateModel-validation.xml]: modelin doğrulama kuralları
- [FormDateModel.properties]: modelin mesaj dosyası
- [example.xml]: Struts'un ikincil yapılandırma dosyası
14.2. Projenin yapılandırılması
Proje, esas olarak aşağıdaki [example.xml] dosyası ile yapılandırılır:
<?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="FormDate" class="example.FormDate">
<result name="input">/example/FormDate.JSP</result>
<result name="cancel" type="redirect">/example/Accueil.JSP</result>
<result name="success">/example/ConfirmationFormDate.JSP</result>
</action>
</package>
</struts>
Bu dosya, tamsayı girişi için incelenen dosyaya benzerdir.
14.3. Mesaj dosyaları
[messages.properties] dosyası şöyledir:
Accueil.titre=Accueil
Accueil.message=Struts 2 - Conversions et validations
Accueil.FormDate=Saisie de dates
Form.titre=Conversions et validations
FormDate.message=Struts 2 - Conversion et validation de dates
FormDate.conseil=Tapez les dates au format JJ/MM/AAAA comme dans 12/10/2008
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
xwork.default.invalid.fieldvalue=Valeur invalide pour le champ "{0}".
[FormDateModel.properties] dosyası şöyledir:
date.format={0,date,dd/MM/yyyy}
date1.prompt=1-Tapez une date au format JJ/MM/AAAA
date1.error=Date erron\u00E9e
date2.prompt=2-Tapez une date au format JJ/MM/AAAA
date2.error=Date erron\u00E9e
date3.prompt=3-Tapez une date >=18/05/2000
date3.error=Date erron\u00E9e
date4.prompt=4-Tapez une date <=20/06/2001
date4.error=Date erron\u00E9e
date5.prompt=5-Tapez une date dans l''intervalle [18/05/2000,20/06/2001]
date5.error=Date errron\u00E9e
date6.prompt=6-Tapez une date dans l''intervalle [18/05/2000,20/06/2001]
date6.error=Date errron\u00E9e
- satır önemli bir rol oynar. Buna daha sonra tekrar döneceğiz.
14.4. Giriş formu
[FormDate.JSP] görünümü ş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="FormDate.message"/></h2>
<h4><s:text name="FormDate.conseil"/></h4>
<s:form name="formulaire" action="FormDate">
<s:textfield name="date1" key="date1.prompt"/>
<s:textfield name="date2" key="date2.prompt" value="%{#parameters['date2']!=null ? #parameters['date2'] : date2==null ? '' :getText('date.format',{date2})}"/>
<s:textfield name="date3" key="date3.prompt" value="%{#parameters['date3']!=null ? #parameters['date3'] : date3==null ? '' :getText('date.format',{date3})}"/>
<s:textfield name="date4" key="date4.prompt" value="%{#parameters['date4']!=null ? #parameters['date4'] : date4==null ? '' :getText('date.format',{date4})}"/>
<s:textfield name="date5" key="date5.prompt" value="%{#parameters['date5']!=null ? #parameters['date5'] : date5==null ? '' :getText('date.format',{date5})}"/>
<s:textfield name="date6" key="date6.prompt"/>
<s:submit key="Form.submitText" method="execute"/>
</s:form>
<br/>
<s:url id="URL" action="FormDate" method="cancel"/>
<s:a href="%{URL}"><s:text name="Form.cancelText"/></s:a>
<br/>
<s:url id="URL" action="FormDate" method="clearModel"/>
<s:a href="%{URL}"><s:text name="Form.clearModel"/></s:a>
</body>
</html>
- ile 18. satırlar, tarih girişi için kullanılan altı alandır. date2 ile date5 arasındaki alanlar, gerçek sayıların girişinde olduğu gibi karmaşık bir value özniteliğine sahiptir. Aynı zorluklarla karşılaşıldığından, bunlar da aynı şekilde çözüldü.
14.5. Onay ekranı
[ConfirmationFormDate.JSP] onay 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="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="date1.prompt"/></td>
<td><s:text name="date1"/></td>
</tr>
<tr>
<td><s:text name="date2.prompt"/></td>
<td>
<s:text name="date.format">
<s:param value="date2"/>
</s:text>
</td>
</tr>
<tr>
<td><s:text name="date3.prompt"/></td>
<td>
<s:text name="date.format">
<s:param value="date3"/>
</s:text>
</td>
</tr>
<tr>
<td><s:text name="date4.prompt"/></td>
<td>
<s:text name="date.format">
<s:param value="date4"/>
</s:text>
</td>
</tr>
<tr>
<td><s:text name="date5.prompt"/></td>
<td>
<s:text name="date.format">
<s:param value="date5"/>
</s:text>
</td>
</tr>
<tr>
<td><s:text name="date6.prompt"/></td>
<td><s:text name="date6"/></td>
</tr>
</table>
<br/>
<s:url id="URL" action="FormDate!input"/>
<s:a href="%{URL}"><s:text name="Confirmation.lien"/></s:a>
</body>
</html>
[ConfirmationFormDate.JSP] görünümü, yalnızca [FormDateModel] şablonunu görüntüler. 47-49. satırlar bir tarihin görüntülenmesini gösterir. Bu gösterimin bir tarih biçimini dikkate almasını istiyoruz. Bunun için, daha önce uygulamanın uluslararasılaştırılması amacıyla kullandığımız <s:text> etiketini kullanıyoruz.
Burada kullanılan mesaj anahtarı date.format'tir. Bu anahtar, [FormDateModel.properties] dosyasında bulunur:
date.format={0,date,dd/MM/yyyy}
Anahtara atanan değer burada bir mesaj değil, bir görüntüleme formatıdır:
- 0, görüntülenecek değeri temsil eden bir parametredir. Burada bu, şablondaki date5 alanı olacaktır.
- date, bir tarihi temsil eder. Daha önce, bir sayı için number kullanılmıştı.
- dd/MM/yyyy, tarih formatını temsil eder. Burada, tarihi gg/aa/yyyy biçiminde istiyoruz. Uygun Java formatı dd/MM/yyyy'dir (d: gün, M: ay, y: yıl)
Etiket
<s:text name="date.format">
<s:param value="date5"/>
</s:text>
, {0, tarih, dd/MM/yyyy} mesajını görüntüler; burada date5 parametresi (2. satır), biçimin 0 parametresinin yerine geçer. Böylece, date5 şablonu gg/aa/yyyy biçiminde görüntülenecektir.
14.6. [FormDateModel] şablonu
[FormDate.JSP] formundaki date1 ile date6 arasındaki alanlar, aşağıdaki [FormDateModel] şablonuna eklenir:
package example;
import java.util.Date;
public class FormDateModel {
// parametresiz oluşturucu
public FormDateModel() {
}
// alanlar
private String date1;
private Date date2 = new Date();
private Date date3 = new Date();
private Date date4;
private Date date5;
private String date6;
// şablon sıfırlama
public void clearModel() {
date1 = null;
date2 = null;
date3 = null;
date4 = null;
date5 = null;
date6 = null;
}
// alıcı ve ayarlayıcılar
...
}
- date1 ve date6 alanları String türündedir
- diğer alanlar Date türündedir
14.7. Şablonun doğrulanması
Modelin doğrulanması iki dosya tarafından kontrol edilir: [FormDate-validation.xml] ve [FormDateModel-validation.xml].
[FormDate-validation.xml] dosyası, doğrulama işlemlerini [FormDateModel-validation.xml] dosyasına devreder:
<!--
<!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-10/example/xwork-validator-1.0.2.dtd">
<validators>
<field name="model" >
<field-validator type="visitor">
<param name="appendPrefix">false</param>
<message/>
</field-validator>
</field>
</validators>
Bu dosyayla daha önce karşılaşmıştık.
[FormDateModel-validation.xml] dosyası aşağıdaki doğrulama kurallarını içerir:
<!--
<!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-11/example/xwork-validator-1.0.2.dtd">
<validators>
<field name="date1" >
<field-validator type="requiredstring" short-circuit="true">
<message key="date1.error"/>
</field-validator>
<field-validator type="regex" short-circuit="true">
<param name="expression">^\d{2}/\d{2}/\d{4}$</param>
<param name="trim">true</param>
<message key="date1.error"/>
</field-validator>
</field>
<field name="date2" >
<field-validator type="required" short-circuit="true">
<message key="date2.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="date2.error"/>
</field-validator>
</field>
<field name="date3" >
<field-validator type="required" short-circuit="true">
<message key="date2.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="date3.error"/>
</field-validator>
<field-validator type="date" short-circuit="true">
<param name="min">18/05/2000</param>
<message key="date3.error"/>
</field-validator>
</field>
<field name="date4" >
<field-validator type="required" short-circuit="true">
<message key="date2.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="date4.error"/>
</field-validator>
<field-validator type="date" short-circuit="true">
<param name="max">20/06/2001</param>
<message key="date4.error"/>
</field-validator>
</field>
<field name="date5" >
<field-validator type="required" short-circuit="true">
<message key="date2.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="date5.error"/>
</field-validator>
<field-validator type="date" short-circuit="true">
<param name="min">18/05/2000</param>
<param name="max">20/06/2001</param>
<message key="date5.error"/>
</field-validator>
</field>
<field name="date6" >
<field-validator type="requiredstring" short-circuit="true">
<message key="date6.error"/>
</field-validator>
<field-validator type="regex" short-circuit="true">
<param name="expression">^\d{2}/\d{2}/\d{4}$</param>
<param name="trim">true</param>
<message key="date6.error"/>
</field-validator>
</field>
</validators>
- 11-20. satırlardaki kural, date1 giriş alanının, jj/mm/aaaa biçiminde bir tarihi temsil eden düzenli ifade şablonuna uygun olup olmadığını kontrol eder. Burada, dizgenin tarih biçiminde olup olmadığı kontrol edilir, ancak geçerli bir tarih olup olmadığı kontrol edilmez. Dolayısıyla 29/02/2011 tarih biçimindedir ancak geçerli bir tarih değildir.
- 22-29. satırlardaki kural, date2 giriş alanının geçerli bir tarih olup olmadığını kontrol eder.
- 31-42. satırlardaki kural, date3 giriş alanının >=18/05/2000 tarihli geçerli bir tarih olup olmadığını kontrol eder
- 44-55. satırlardaki kural, date4 giriş alanının <=20/06/2001 tarihli geçerli bir tarih olup olmadığını kontrol eder.
- 57-69. satırlardaki kural, date5 giriş alanının <=20/06/2001 ve >=18/05/2000 aralığında geçerli bir tarih olup olmadığını kontrol eder.
- 71-80. satırlardaki kural, date6 alanının gg/aa/yyyy biçiminde bir tarih olup olmadığını kontrol eder.
[FormDateModel-validation.xml] dosyası doğrulama yakalayıcısı tarafından işlendiğinde, yakalayıcı, varsa [FormDate] eyleminin validate yöntemini çalıştırır. Bu yöntemi, eylemin tamamıyla birlikte sunacağız.
14.8. [FormDate] eylemi
[FormDate] eylemi şu şekildedir:
package example;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.interceptor.validation.SkipValidation;
public class FormDate extends ActionSupport implements ModelDriven, SessionAware {
// parametresiz oluşturucu
public FormDate() {
}
// eylem şablonu
public Object getModel() {
if (session.get("model") == null) {
session.put("model", new FormDateModel());
}
return session.get("model");
}
@SkipValidation
public String clearModel() {
// şablon sıfırlama
((FormDateModel) getModel()).clearModel();
// sonuç
return INPUT;
}
public String cancel() {
// modeli temizliyoruz
((FormDateModel) getModel()).clearModel();
// sonuç
return "cancel";
}
// SessionAware
Map<String, Object> session;
public void setSession(Map<String, Object> session) {
this.session = session;
}
// doğrulama
@Override
public void validate() {
// tarih biçimlendirme
SimpleDateFormat formateurDate = new SimpleDateFormat("dd/MM/yyyy");
formateurDate.setLenient(false);
// tarih1 girişi geçerli mi?
if (getFieldErrors().get("date1") == null) {
// tarihin geçerliliğinin kontrolü
try {
formateurDate.parse(((FormDateModel) getModel()).getDate1());
} catch (Exception e) {
addFieldError("date1", getText("date1.error"));
}
}
// tarih6 girişi geçerli mi?
if (getFieldErrors().get("date6") == null) {
Date d = null;
try {
// tarihin geçerliliğinin kontrolü
d = formateurDate.parse(((FormDateModel) getModel()).getDate6());
// sınırların kontrolü
if (d.after(formateurDate.parse("20/06/2001")) || d.before(formateurDate.parse("18/05/2000"))) {
addFieldError("date6", getText("date6.error"));
return;
}
} catch (Exception e) {
addFieldError("date6", getText("date6.error"));
return;
}
}
}
}
[FormDate] eylemi, [FormInt] eylemi ile aynı model üzerine kurulmuştur. Yalnızca validate yöntemini ele alacağız. validate yönteminin, [FormDateModel-validation.xml] doğrulama dosyasının işlenmesinden sonra ve execute yönteminin yürütülmesinden önce çalıştırıldığını hatırlatırız.
- validate yöntemi, date1 ve date6 yöntemlerinin tarih doğrulama işlemlerini tamamlar. [FormDateModel-validation.xml] doğrulama dosyası, girilen dizelerin tarih biçiminde olup olmadığını kontrol etmişti. Şimdi bunların gerçekten geçerli tarihler olup olmadığı kontrol ediliyor. Ayrıca, date1 ve date6'in, şablondaki String türündeki tek iki alan olduğunu da hatırlatmak isteriz.
- 50. satır: Bu tür dizelerin gerçekten geçerli tarihler olup olmadığını doğrulamak için gg/aa/yyyy tarih biçimi oluşturulur.
- 51. satır: setLenient(false) ifadesi, geçersiz tarih olan 32/01/2012'nin geçerli tarih olan 01/02/2012 olarak yorumlanmasını önler.
- 53. satır: date1, yalnızca önceki doğrulama işlemlerinde bu alanda hata oluşmamışsa geçerli kabul edilir.
- 56. satır: date1'in gg/aa/yyyy biçiminde geçerli bir tarih olup olmadığı kontrol edilir.
- 58. satır: Eğer geçerli değilse, date1 alanına bir hata mesajı atanır.
- 62. satır: date6 alanı, yalnızca önceki doğrulamaları geçmişse geçerli kabul edilir.
- satır 66: date6'in geçerli bir tarih olup olmadığı kontrol edilir
- 68. satır: date6, <18/05/2000 veya date6>20/06/2001'den önceyse, date6 hatalıdır.
14.9. Son ayrıntılar
Önceki formda, aşağıdaki örnekte gösterildiği gibi bazı hatalar bulunmaktadır:
![]() |
- [1]'te geçersiz bir tarih girildiğinde
- [2]'te ise kabul edilmiştir. Yalnızca ilk karakterler gg/aa/yyyy dikkate alınmıştır.
Date türü şablonlarla ilişkili olan date2 ile date5 arasındaki tüm alanlarda bu sorun mevcuttur. Yine de, belki de belgelerde bir şeyi gözden kaçırmış olabilirim. String türündeki şablonlarla ilişkili olan date1 ve date6 alanlarında bu sorun görülmemektedir.



