Spring Mvc Uygulama Catisi Osunercan Wwwjavadilicom

  • Uploaded by: www.javadili.com
  • 0
  • 0
  • December 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Spring Mvc Uygulama Catisi Osunercan Wwwjavadilicom as PDF for free.

More details

  • Words: 8,365
  • Pages: 32
Spring MVC Uygulama Çatısı

Ömer SUNERCAN [email protected]

2006, Ankara

İçindekiler Giriş......................................................................................................................................................3 Belge İçeriği Hakkında....................................................................................................................3 Spring MVC..........................................................................................................................................3 Geliştirme Ortamının Hazırlanması.................................................................................................3 Kurulum......................................................................................................................................3 Uygulama Kılavuz Yapısının Oluşturulması...............................................................................4 Başlangıç (DispatcherServlet).........................................................................................................4 İlk Spring MVC Örneği...................................................................................................................5 Uygulamaya Başlıyoruz.................................................................................................................11 Ana Sayfa.......................................................................................................................................13 Form Kullanımı..............................................................................................................................15 Araç Girişi......................................................................................................................................17 Doğrulama (Validation).................................................................................................................23 Durdurucular (Interceptors)...........................................................................................................28 Sonuç..................................................................................................................................................31 Terimler Sözlüğü................................................................................................................................32 Kaynaklar............................................................................................................................................32

Giriş Spring, son dönemde J2EE uygulaması geliştirme alanında popülerlik kazanan ve yaygın olarak kullanılmaya başlanılan  bir uygulama geliştirme çatısıdır (application framework). Uygulama geliştirmeyi ve denetimi zorlaştıran ağır (heavy­ weight) çözümlere alternatif olarak hafif (lightweight) bir yapı sunarken, aynı zamanda esnek ve modüler bir şekilde bir  çok özelliği içerisinde barındırması Spring'e gösterilen ilgide önemli rol oynar. Spring, birbirinden bağımsız ve ihtiyaca göre kullanımına karar verilebilecek bir çok farklı özellik içerir. Bu özellikler  çatıyı oluşturan yedi farklı birim tarafından sağlanır. Bu belge bunlardan Web MVC (Model View Controller / Model  Görüntüm Denetim)  biriminin kullanımını  örneklemek amacı ile hazırlanmış olduğu için bu birimlerin tek tek ele  alınmasına yer verilmeyecektir. Spring temel olarak, bileşenleri XML yapılandırma kütükleri aracılığıyla bütünleştirmeye dayalı bir yapı sunar. Bu  yaklaşım esas olarak Denetim Çevrimi (Inversion of Control), diğer bir adıyla Bağımlılık İletimi (Dependency Injection),  tasarım   örüntüsünü   kullanır.   Buna   göre,   bileşenler   arasındaki   bağımlılıklar   bileşenlerin   kendileri   yerine   Spring  tarafından ele alınır.  Spring bileşenleri bir araya getirmek ve biçimlendirmek için Java çekirdeklerini (JavaBean) kullanır. Sınıfları kodlanan  bu   çekirdeklere   dair     isimlendirmelerin   yapılması,   gerekli   ilk   değer   atamaları   ve   diğer   çekirdeklerle   aralarındaki  bağımlılıkların tanımlanması XML yapılandırma kütüklerinin içerisinde yapılır. Spring, bu kütükleri okur ve buradaki  tanımları   kullanarak   çekirdek   olgularını   gerekli   yapılandırmaları   gerçekleştirerek   oluşturur.   Bu   işleyiş   sayesinde  uygulamadaki bileşenlerin yapılandırılması ve kullanımı kodun içine girmeye gerek kalmadan, yapılandırma kütükleri  aracılığıyla son derece esnek ve kolay bir biçimde gerçekleştirilir. İleride ele alacağımız Web MVC birimi örneklerinde  bunu çok daha somut şekilde görme ve inceleme olanağı bulacağız.   

Belge İçeriği Hakkında... Bu belgede yoğun bir şekilde bilgiye yer vermek yerine, Spring MVC ile başlangıç düzeyinde basit bir uygulamanın  geliştirilmesi örneklenmeye çalışılacaktır. Özellikle başlangıç aşamasında kavranılmakta zorlanılabilen kavramlara ve  geliştirme sürecinde ortaya çıkabilen temel sorunlara yönelik çözümlere yer verilecektir.    Bu belgede anlatılanların iyi kavranılabilmesi için temel J2EE bilgisine (JSP/Servlet, JSTL, JSP EL) yeteri kadar sahip  olunması gerekmektedir. Spring MVC çatısının kullanımı tamamen giriş düzeyinde ele alınmış olup, bazı noktalarda  atıflar bulunsa da okuyucunun Struts vb. bir çatıyı daha önce kullanmış veya biliyor olması gereksinimi yoktur. Belge içinde verilecek olan kodların tamamı çalıştırılarak denenmiş kodlar olmalarının yanısıra, okuyucuya kolaylık  olması   amacıyla,   tekrar   tekrar   verilen   kaynak   (java)   ve   yapılandırma   (xml)   kütüklerinin   içieriklerinin   sadece  güncellenen kısımları değil, her her seferinde tamamı verilecektir.    Son olarak, MVC'nin Spring'in bir alt bölümü olduğundan hareketle metnin içerisinde bir çok yerde Spring MVC yerine  sadece  Spring  ifadesine yer verilecektir, bunun bir kavram kargaşasına yer açmaması için hatırda tutulmasında fayda  vardır.

Spring MVC Bu bölümde Spring MVC çatısının kullanımını baştan sona adım adım ilerleyerek geliştireceğimiz bir uygulama ile  örnekleyeceğiz.

Geliştirme Ortamının Hazırlanması Kurulum Örnek uygulamamızı gerçekleştirmeye uygun bir çalışma ortamı hazırlayarak başlayacağız.  Spring MVC ile bir J2EE uygulaması geliştirmeye başlamak için öncelikli ihtiyaçlarımız bir Java SDK'sı ve bir Servlet  Kozası  (Servlet Container)  'dır.  Örnek uygulamamız jdk1.5.0 Java SDK'sı ve koza olarak da Apache Tomcat 5.5.9  üzerinde çalışacaktır. Kullanılabilecek   değişik   araçlardan   bağımsız   olması   için   derleme,   yükleme   vb.   amacıyla   herhangi   bir   araç  kullanmayacağız. Siz isteğinize bağlı olarak Ant gibi bir araç veya seçtiğiniz bir IDE kullanarak bu işlemleri alışagelmiş  olduğunuz bir şekilde gerçekleştirebilirsiniz. Bu nedenle bu işlemlere dair ayrıntılara yer verilmeyecektir. 

Yukarıdaki   kısım   herhangi   bir   J2EE   uygulaması   için   gerekli   olan   ortama   ilişkin   ihtiyaçlardı.   Spring   MVC'yi  kullanabilmek   için  www.springframework.org/download.html  adresinden   Spring   çatısını   indirmeniz   gerekmektedir.  Burada karşınıza iki seçenek çıkacaktır: spring­framework­<sürüm_no>.zip spring­framework­<sürüm_no>­with­dependencies.zip İlk seçenek sadece Spring çatısını içerirken, ikinci seçenekle birlikte J2EE uygulaması geliştirmek için gereken diğer bir  çok arşiv de gelir.  Uygulamamızda spring­framework­1.2.5­with­dependencies.zip kurulumu kullanılacak. Spring çatısını indirdikten sonra istediğiniz bir yere açtığınızda kurulum  tamamlanmıştır. Uygulamamızı geliştirme  aşamasında gerektikçe buradan Spring MVC çatısına ilişkin arşivleri uygulamamızın içine dahil edeceğiz. 

Uygulama Kılavuz Yapısının Oluşturulması Uygulamamızı  geliştirmeye gerekli kılavuzları oluşturarak başlayabiliriz. Uygulamamızın adı  springornek  olsun, bu  durumda uygulamamız için kök kılavuzun adı da  springornek  olmalıdır. Öncelikle bir J2EE uygulaması için standart  olan WEB­INF kılavuzunu ve web.xml kütüğünü oluşturmamız gereklidir. <web-app version="2.4"> Kod 2.1 springornek/WEB-INF/web.xml J2EE standardı olarak sınıflar için classes  kılavuzunu ve ekleyeceğimiz kütüphaneler için  lib  kılavuzunu oluşturalım.  Biz Java kaynak kodlarını koymak üzere WEB­INF'in altında bir  src  kılavuzu öngörüyoruz, siz kullanacağınız araca  veya isteğinize göre size uygun seçimi tercih edebilirsiniz. Son olarak JSP sayfalarımızı koymak için  WEB­INF/jsp  kılavuzunu oluşturalım. Bu şekilde JSP sayfaları dışarıdan doğrudan erişime kapatılır ve uygulamadan fiziksel olarak  sistemde bulunmayan sayfalara işaret eden adreslerin (url) yönlendirilmesi yoluyla sistemden hizmet alınabilir.  Gördüğünüz   gibi   Spring   çatısını   kullanmak   için   herhangi   bir   uygulamadan   farklı   bir   yapıya   ihtiyaç   duyulmuyor.  Spring'in aktif olarak kullanımı için yapılması gereken tek şey ileride açıklayacağımız üzere gerekli jar arşivlerini  lib  kılavuzunun içerisine koymak ve XML yapılandırma kütüklerinin içeriğini düzenlemek olacak.

Başlangıç (DispatcherServlet) Spring   MVC,   Spring   çatısı   içerisinde  MVC  (Model   View   Controller   /   Model   Görünüm   Denetim)  mimarisinin  gerçekleştirildiği birimdir. Bilindiği gibi MVC bir uygulamada kullanıcıya sunulan görüntü  (view),  veri  (model)  ve  kullanıcıdan gelen taleplere karşılık olarak veriler üzerinde işlemleri gerçekleştiren denetim  (controller)  bölümlerini  birbirinden ayırmayı öngören bir yaklaşımdır. Bu yaklaşımın J2EE uygulamalarındaki esaslarından birisi Ön Denetimci   Servlet (Front Controller Servlet)'in gelen tüm HTTP isteklerini (request) karşılaması ve bu isteği tanımlanan eşlemelere  (mapping) göre değerlendirip yanıtı (response) üretecek olan işleyicilere (handler) yönlendirmesidir.   Spring MVC'de Ön Denetimci (Front Controller) Servlet olarak DispatcherServlet hizmet verir. Spring MVC'de  işleyicilere karşılık olarak da Controller arayüzünü (interface) uygulayan (implement) sınıflardır.  Artık Spring MVC'yi uygulamamızın içine dahil etmenin zamanı geldi. Bunun için öncelikle Spring kurulumunuzun  içindeki spring.jar (spring­framework­1.2.5/dist/spring.jar) arşiv kütüğünü WEB­INF/lib kılavuzunun içine kopyalayın.  Spring kütüphanesini uygulamaya dahil ettiğimize göre artık Spring'e özel işlemler yapmaya başlayabiliriz. Yukarıda  Spring'de  Ön Denetimci  olarak  DispatcherServlet  Servlet'inin işlev gördüğünden söz etmiştik. Bu nedenle ilk  adım olarak uygulamaya gelen tüm istekleri bu Servlet'e yönlendirmeli ve böylece uygulamanın denetimini tamamen  Spring'e bırakmalıyız. Bunu gerçekleştirebilmek için  web.xml  kütüğüne bir Servlet tanımı eklememiz gerekiyor (Kod  2.2). Görüldüğü üzere uygulamamızın adı olan  springornek  adı ile bir Servlet tanımı ekliyoruz ve Servlet sınıfı olarak da  DispatcherServlet'i belirtiyoruz. Ayrıca  htm  ile sonlanan tüm url'lerin bu Servlet'e yönlendirilmesi gerektiğini  belirtiyoruz. Buna göre bu uygulamaya gelen (<sunucu>/springornek ile başlayan) ve htm ile sona eren url'ler Spring'in  DispatcherServlet'i tarafından değerlendirilecek ve buna isteğe buna göre cevap verilecektir. 

<web-app version="2.4"> <servlet> <servlet-name>springornek <servlet-class> org.springframework.web.servlet.DispatcherServlet         1 <servlet-mapping> <servlet-name>springornek *.htm Kod 2.2 springornek/WEB-INF/web.xml Yeri   gelmişken  DispatcherServlet'in   davranışını   belirleyen   tanım   ve   yapılandırılmaların   bulunduğu   XML  yapılandırma kütüğüne değinelim. Spring MVC çatısı bu yapılandırma kütüğü için

­servlet.xml şeklinde   bir   adlandırma   öngörmüştür.   Bu   durumda   bizim   yapılandırma   kütüğümüzün   adı  springornek­servlet.xml  olmalıdır ve bu kütüğün springornek/WEB­INF/ kılavuzunun altında bulunması gerekmektedir. Bu kütüğün henüz hiç  bir tanım yapılmamış haldeyken görünümü Kod 2.3'de veriliyor.  Kod 2.3 springornek/WEB-INF/springornek-servlet.xml İleride gerekli tüm tanımlamaları beans etiketleri arasına ekleyeceğimiz bean etiketleri ile bu kütükte yapacağız.

İlk Spring MVC Örneği Spring MVC kullanarak hazırlayacağımız bir sayfa için temel olarak iki kütüğe ihtiyacımız vardır. Bir görünüm (view)  ve bir denetimci  (controller). Spring MVC birden fazla görünüm teknolojisine destek vermektedir  (JSP/JSTL, Tiles,   Velocity, FreeMaker  vs.). Bizim uygulamamızdaki tüm  görünümler JSP  (ve JSTL) ile oluşturulacaktır. Bu nedenle  görünüm  kelimesinin geçtiği noktalarda bir JSP sayfasından bahsediyor olacağız.  Denetimciler (controller) daha önce söz edildiği üzere bir HTTP isteğini (request) değerlendiren ve buna göre bir yanıt  (response) üretip, bu sonuca uygun bir sayfaya yönlendirme işini yapan sınıflardır. Spring MVC, isteklerin türüne göre  en uygun ve en kolay kodlamayı sağlayabilmek için farklı denetim sınıfları içermektedir. Yani örneğin sadece metin ve  bir takım bağlantılardan (link) oluşan bir sayfa için farklı, bir submit olayı sonucu üretilen ve form verisi taşıyan bir istek  için farklı ve daha uygun bir sınıftan türetilen denetimciler kullanılabilir.  Denetimci sınıfların en üst düzeydeki atası Controller arayüzüdür. Struts kullanmış olanlar için bunun Action'a  karşılık geldiğini söyleyebiliriz. public interface Controller { ModelAndView handleRequest( HttpServletRequest request, HttpServletResponse response) throws Exception; } Kod 2.4 org.springframework.web.servlet.mvc.Controller Kod 2.4'te Controller sınıfının koduna yer verilmiştir. Controller arayüzü handleRequest()adlı yönetimi 

sağlar. Bu arayüzü uygulayan sınıflarda bu yöntemin içerisinde istek (request) için yerine getirilmesi gerekenler kodlanır  ve   bu   yöntem   geriye   bir  org.springframework.web.servlet.ModelAndView  nesnesi   döndürülür.   Bu  nesne sınıf adından da anlaşıldığı gibi yanıt için gerekli olan veriyi (model) de görünümü (view) de taşır. Bunların bir  arada   gönderilmesinin   sebebi   kullanıcıya   gösterilecek   görünüme   aynı   zamanda   sunacağı   veriyi   de   sağlanmasıdır.  Örneğin bir JSP sayfasının kullanıcının seçimi için listeleyeceği seçeneklerle ilgili veriye erişmesi gerekir  (örneğin  request  nesnesi   üzerinden).   Bu   nesnenin  (ModelAndView   nesnesi)  oluşturulması   ve   kullanımını   uygulamamızın  içinde örnekleyeceğiz. 

RequestUtils org.springframework.web.bind.RequestUtils  sınıfı,  HttpServletRequest    bir   nesnesinin  parametrelerine   parametrenin   türünü   belirterek   erişim   sağlayan  static  yöntemler   içerir.   Parametrelere  HttpServletRequest  nesnesinin üzerinden doğrudan erişmek yerine bu sınıfı kullanmak tavsiye edilen bir  yöntemdir. Örnekler:     String str = RequestUtils.getStringParameter(request, "string_param");     int i = RequestUtils.getIntParameter(request, "int_param", 0);     Integer i = RequestUtils.getIntParameter(request, "integer_param");

Şu ana kadar açıkladıklarımıza dayanarak bir isteğin hangi aşamalardan geçerek bir yanıta dönüştüğünü sıralarsak, istek  ilk önce DispatcherServlet tarafından ele alınır, bu Servlet ileride açıklayacağımız eşleme (mapping)  yapılandırmasını kullanarak isteği bir denetimciye yönlendirir. Denetimci isteğe dair yapılması gereken işlemleri  gerçekleştirdikten sonra bir ModelAndView nesnesi döndürür. Bu nesne hangi hangi sayfanın gösterileceği bilgisinin  yanı sıra sunulacak veriye de sahiptir ve bunlardan üretilen bir yanıt (response) kullanıcıya döndürülür. Denetimciler ve diğer ayrıntılara girmeden önce artık “Merhaba Dünya!” mesajını  gösteren bir ana sayfa yapmaya  geçmeliyiz. Öncelikle sitenin girişi niteliğide olan bir index.jsp hazırlamalıyız. Bir J2EE web uygulamasında sitenin açılış sayfası  (ana sayfası) web.xml kütüğüne welcome­file etiketi içerisnde verilir ve burada verilen sayfanın açılışta görüntülenmesi  için kullanıcıların erişimine açık fiziksel bir kütüğe işaret ediyor olması gerekir. Bu nedenle index.jsp sayfasını WEB­ INF/jsp kılavuzuna değil doğrudan uygulamanın kök kılavuzuna koymalıyız (springornek/index.jsp).  <web-app version="2.4"> <servlet> <servlet-name>springornek <servlet-class> org.springframework.web.servlet.DispatcherServlet         1 <servlet-mapping> <servlet-name>springornek *.htm <welcome-file-list> <welcome-file>index.jsp Kod 2.5 springornek/WEB-INF/web.xml Kod 2.5'te görüldüğü gibi web.xml kütüğünü günledikten sonra, Kod 2.6'daki index.jsp sayfasını kaydedip uygulamayı  çalıştırdığınızda karşınıza “Merhaba Dünya!” yazan bir sayfa çıkması gerekir. Ancak daha önce söz ettiğimiz gibi JSP'lerimizin kullanıcıların doğrudan erişimine açık olmasını istemiyoruz ve ana  sayfada   da   dahil   tüm   görünümlerin   Spring   tarafından   arka   planda   oluşturulmasını   ve   kullanıcılara   sadece   sanal  url'lerden  (.htm   uzantılı)  haberdar   olmasını   istiyoruz.   Ancak   dışarıdan   erişilebilir   bir  index.jsp'den  vazgeçemeyeceğimize göre bu durumda çözüm index.jsp'nin hiç bir bilgi ya da görüntü içermeyip, isteği (request) başka  bir sayfaya yönlendirmesidir (Kod 2.7).

<%@ page contentType="text/html; charset=ISO-8859-9" %> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> Merhaba Dünya

Merhaba Dünya!

Kod 2.6 springornek/index.jsp <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> Kod 2.7 springornek/index.jsp Artık  index.jsp  kendisine gelen istekleri  springornek/index.htm  adresine yönlendiriyor. Peki bu adres karşılığında ne  yapılacak? Hangi sayfa görüntülenecek? Burada devreye Spring'in sağladığı Görünüm Çözlümleyici (View Resolver) ve  İşleyici Eşleme (Handler Mapping) sınıfları giriyor.  Daha önce denetimci  (Controller)  sınıfların gerekli işlemleri yerine getirdikten sonra bir  ModelAndView  nesnesi  döndürdüğünden   söz   etmiştik.   Spring'de   görünümler  (view)  biricik   String'ler   ile   ifade   edilebilirler.   Görünüm  çözümleyiciler (view resolver) bu String'lere göre doğru görünümleri tespit edip yönlendirmelerin yapılmasını sağlarlar.  Daha   önce   söylediğimiz   gibi   Spring   birden   fazla   görünüm   teknolojisini   destekler   ve   bu   nedenle   çeşitli   görünüm  çözümleme   sınıfları   sunar.   JSP   teknolojisi   kullanılıyorsa   uygun   olan   görünüm   çözümleme   sınıfı  org.springframework.web.servlet.view.UrlBasedViewResolver'dır. Bizim uygulamamızda olduğu  gibi   eğer   JSP   ve   JSTL   teknolojileri   bir   arada   kullanılacaksa   en   uygun   çözüm  org.springframework.web.servlet.view.InternalResourceViewResolver  sınıfını  kullanmaktır.  Görünüm   çözümleyici   sınıfın  DispatcherServlet  tarafından   nesnesinin   oluşturulup   görünüm   çözümlemede  kullanılabilmesi   için  springornek­servlet.xml  yapılandırma   kütüğüne   bu   sınıfa   dair  çekirdek  (bean)  tanımını   ve   ilk  değerlerini vermemiz gerekir (Kod 2.8). <property name="viewClass"> org.springframework.web.servlet.view.JstlView <property name="prefix">/WEB-INF/jsp/ <property name="suffix">.jsp Kod 2.8 springornek/WEB-INF/springornek-servlet.xml Uygulama başlatıldığında yapılandırma kütüğüne eklediğimiz  bu çekirdeğin nesnesi  oluşturulur. Burada  verilen ilk  değerlere göre bir görünümü  (view)   ifade etmek için kullanılan  String'in başına /WEB­INF/jsp/  öneki  (prefix)  ve  sonuna .jsp soneki (suffix) getirilerek görünüme dair gerçek adrese ulaşılabilir. Buna göre örneğin bir ModelAndView  nesnesi oluştururken belirtilen önek ve sonekleri yazma zahmetine katlanmadan görünüm belirlenebilir. Örneğin /WEB­ INF/jsp/hello.jsp görünümüne sadece hello anahtarıyla erişilebilir.  Ancak henüz sorduğumuz soruların cevabını bulamadık. Yani  /springornek/index.htm adresinin nereyi gösterdiği kısmı  henüz   belirsizliğini   koruyor.   Öncelikle   bu   adrese   karşılık   gelen,   bu   isteği   karşılayan   bir   görünümümüz   ve   bir  denetimcimizin bulunması gerekir. Bu amaçla kısa bir mesaj içeren küçük bir sayfa yapalım. Bu küçük örnek için  doğrudan  Controller  arayüzünü   uygulayan   bir   sınıfımızın   bulunması   yeterli   olacaktır.   Denetimci   sınıflar   için 

denetim adlı bir paket (package) oluşturalım ve burada ilk denetimcimizi oluşturalım.  package denetim; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; public class BasitDenetimci implements Controller { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { return new ModelAndView("basit"); }

} Kod 2.9 springornek/WEB-INF/src/denetim/BasitDenetimci.java

Kod 2.9'da verilen BasitDenetimci sınıfı isteği (request) bir görünüme yönlendirmek dışında bir işlem yapmıyor.  ModelAndView  nesnesi oluşturulurken yapılandırıcısına sadece görünüm ismi veriliyor. Daha önce tanımladığımız  görünüm   çözümleyici  (view   resolver)  “basit”  adıyla   tanımladığımız   görünüme   karşılık  springornek/WEB­ INF/jsp/basit.jsp sayfasını getirecektir ve DispatcherServlet tarafından istek bu sayfaya yönlendirilecektir. Sayfa  herhangi   bir   veriye   ihtiyaç   duymayacağı   için  ModelAndView  nesnesi   herhangi   bir   veri  (model)  eklemeden  oluşturulup  döndürülmektedir.  Yazdığımız denetimci sınıfın DispatcherServlet tarafında tanınıp gerekli yönlendirmelerde kullanılabilmesi için  onu yapılandırma kütüğüne eklememiz gerekmektedir (Kod 2.10). <property name="viewClass"> org.springframework.web.servlet.view.JstlView <property name="prefix">/WEB-INF/jsp/ <property name="suffix">.jsp Kod 2.10 springornek/WEB-INF/springornek-servlet.xml Bu   tanımın   eklenmesiyle   birlikte   uygulama   çalıştırıldığında,  BasitDenetimci  sınıfının   bir   olgusu  basitDenetimci  adıyla   Spring   tarafından   oluşturulacaktır.   Bu   nesne   aynı   zamanda   gerektiğinde   (örneğin  yönlendirmelerin tanımlanmasında) bu adla çekirdek (bean) diğer tanımlamalarında da kullanılabilecktir.  Oluşturacağımız sayfanın görünümünü oluşturan basit.jsp Kod 2.11'de verilmiştir.  Şu   anda   basit   bir   mesaj   sayfasını   görüntülemek   için   gerekli   her   şey   hazır   durumda.   Ancak   tek   eksik  DispatcherServlet'in springornek/index.htm adresini BasitDenetimci denetimcisine yönlendirmesi. Bunun  için Spring'in daha önce söz konusu ettiğimiz İşleyici Eşleme (Handler Mapping) işlevini kullanmalıyız.

<%@ page contentType="text/html; charset=ISO-8859-9" %> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> springornek

Hoşgeldiniz!

Örnek Spring MVC uygulaması. Kod 2.11 springornek/WEB-INF/jsp/basit.jsp Spring   MVC   görünüm   çözümleme   konusunda   olduğu   gibi   işleyici   eşleme   konusunda   da   çeşitli   sınıflar   sunar.   Bu  sınıfların   çekirdek   tanımlarına   yapılandırma   kütüğünde   yer   verilerek   ve   burada   gerekli   eşleştirmeler   yapılarak  uygulamada hangi url'nin hangi  denetimci tarafından değerlendirileceğini   belirlenir. Yani bir anlamda uygulamada  kullanılan adreslerin tamamen soyut olması, başka bir deyişle fiziksel  bir kütüğe işaret etmesine gerek kalmaması  sağlanır. Bu işlevin getirdiği avantajlardan birisi de adresleri belirlemede uzantı vs. kısıtlamalarının bulunmamasıdır.  Bizim uygulamamızdaki url'ler  .htm  uzantısı ile sonlanacaktır. Ancak bu bir tercihten öteye geçmemektedir örneğin  istenirse hiç bir uzantı da kullanılmayabilir.  Biz, uygulamamızda işleyici eşleme amacıyla  org.springframework.web.servlet.handler  paketindeki  SimpleUrlHandlerMapping  sınıfını   kullanacağız.   Bu   sınıf,   tanımlamalarda   Ant   stili   (örneğin   *,   **   gibi  sembollerle toplu olarak eşleştirmelere olanak verir) ifadelere izin veren ve güçlü özellikleri olan bir eşleme sınıfıdır.  Başlangıç sayfası olarak yönlendirilen  index.htm  adresinin  BasitDenetimci  tarafından ele alınacağını ifade eden  eşlemeyi Kod 2.12'deki gibi tanımlayabiliriz. <property name="mappings"> <props> <prop key="/index.htm">basitDenetimci <property name="viewClass"> org.springframework.web.servlet.view.JstlView <property name="prefix">/WEB-INF/jsp/ <property name="suffix">.jsp Kod 2.12 springornek/WEB-INF/springornek-servlet.xml SimpleUrlHandlerMapping türünde urlEsleme adında çekirdek oluşturuluyor. Bu çekirdeğin mappings adlı  niteliğinin içine tüm eşlemelere yer verilir. Yeni bir eşleme ekleyeceğimizde  yeni bir  prop  etiketi eklememiz yeterli  olacaktır.

Şu anda  çalışabilir  bir  örneği   elde  etmiş surumdayız. Uygulamanın  başlangıç  sayfası  index.jsp,  index.htm  adresine  yönlendirme yapar, bu adresin basitDenetimci denetimcisi tarafından ele alınacağına karar verilir, son olarak denetimci  basit  görünümüne  (springormek/WEB­INF/jsp/basit.jsp)  yönlendirir ve bu sayfanın içeriğini tarayıcıda Resim 2.1'deli  gibi görürüz.

Resim 2.1 Başlangıç Sayfası ModelAndView  nesnesinin   veri  (model)  kısmı   bir   harita   mantığı   ile   çalışır.  BasitDenetimci'yi  biraz  değiştirerek görünüme bilgi göndermesini sağlayalım (Kod 2.13). ModelAndView'e   iki   biçimde   veri   ekleyebildiğimizi   görüyoruz.   Bunlardan   ilki  ModelAndView  nesnesinin  yapılandırıcısına görünümün ardından anahtar kelime  (bir String)  ve veriyi  (bir Object)  parametre olarak vermektir.  İkincisi ise benzer şekilde addObject yöntemini kullanmaktır. Bu yöntem kullanılarak ModelAndView nesnesine  istenildiği kadar veri eklenilebilir.   package denetim; import java.util.Date; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; public class BasitDenetimci implements Controller { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView( "basit", "mesaj", "Bu String türündeki mesaj verisi!"); mav.addObject("birSayi", new Integer(555)); mav.addObject("tarih", new Date()); return mav; }

} Kod 2.13 springornek/WEB-INF/src/denetim/BasitDenetimci.java

Bu   durumda   görünümü   de   gönderilen   verileri   görüntülemek   amacıyla   biraz   değiştirmemiz   gerekiyor   (Kod   2.14).  Görünüm   içinden   bu   verilere   istek  (request)  nitelikleri   olarak   erişilebilir.   Niteliğe   erişmek   için  ModelAndView  nesnesine veriyi koyarken kullandığımız  anahtar kelimeyi kullanabiliriz. Örneklerimizde JSP EL söz dizimini (syntax)  kullanacağız ve örneğin “mesaj” anahtar kelimesini kullandığımız  String  türü veriye sayfanın herhangi bir yerinde  ${mesaj}  şeklinde erişebiliriz. Son değişikliklerden sonra uygulama çalıştırıldığında Resim 2.2'deki görüntü elde  edilir. <%@ page contentType="text/html; charset=ISO-8859-9" %> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> springornek

Hoşgeldiniz!

Örnek Spring MVC uygulaması.


<em><strong>Veriler:

Mesaj: <em>${mesaj}
Bir sayı: <em>${birSayi}
Tarih: <em>${tarih} Kod 2.14 springornek/WEB-INF/jsp/basit.jsp

Resim 2.2 Denetmicinin Gönderdiği Veriye Erişim

Uygulamaya Başlıyoruz Artık Spring MVC kullanarak basit web uygulaması geliştirmek için temel altyapımız hazır durumda olduğuna göre  kendi uygulamamızı inşa etmeye başlayabiliriz. Bu esnada Spring'in form içeren sayfalarda form verilerinin kontrolünü  kolaylaştıran,   kullanıcı   tarafından   girilen   verileri   doğrulama  (validation)  işlemini   uygulama   kodundan   ayıran   ve  yalınlaştıran, istek denetimciye ulaşmadan önce ve sonra yapılması gereken işlemlerin gerçekleştirilmesine olanak veren  bir yapı (interceptors) sağlayan çeşitli işlevlerini inceleyeceğiz.  Bunlar gibi bir çok işleve değinecek olmamıza rağmen  takip etmeyi kolaylaştırmak ve karışıklığa sebep olmamak için olabildiğince az sayıda sayfaya yer vereceğiz.   Uygulamamız, bir otoparka giriş yapan araçlara otopark gişesinde boş olan bir park yerinin verilmesi (sıradaki yer veya  seçilen boş bir yer) ve park yeri verilen aracın plakasının ve park yerinin kaydedilmesi işlemlerini içerecektir. Önce 

sayfaları  hazırlarken kullanacağımız, araçlara ve otoparka  dair verileri  tutan ve  bunlara  erişim  sağlayan iş mantığı  sınıflarını kodlayarak başlayalım (Kod 2.15, 2.16) ve bu sınıfları ismantigi adlı bir paketin içerisinde toplayalım. package ismantigi; public class Arac { //plaka alanları int ilKodu; String harfKodu; int aracNo;

}

public int getAracNo() { return aracNo; } public void setAracNo(int aracNo) { this.aracNo = aracNo; } public String getHarfKodu() { return harfKodu; } public void setHarfKodu(String harfKodu) { this.harfKodu = harfKodu; } public int getIlKodu() { return ilKodu; } public void setIlKodu(int ilKodu) { this.ilKodu = ilKodu; } Kod 2.15 springornek/WEB-INF/src/ismantigi/Arac.java

package ismantigi; public class Otopark { public final static int ARAC_SAYISI = 10; private static Arac[] araclar = new Arac[ARAC_SAYISI]; private static int ilkBosYer = 0; static { for(int i = 0; i < ARAC_SAYISI; ++i) araclar[i] = null; } public static void aracParket(Arac arac, int parkYeri) { araclar[parkYeri] = arac; if(ilkBosYer == parkYeri) { int gecici = ilkBosYer; do { ilkBosYer = (ilkBosYer + 1) % ARAC_SAYISI; if(ilkBosYer == gecici) { //Boş yer yok ilkBosYer = -1; break; } } while(araclar[ilkBosYer] != null);//dolu Mu? } }

public static boolean doluMu(int parkYeri) { return araclar[parkYeri] != null; } public static boolean doluMu() { return ilkBosYer == -1; } public static Arac[] getAraclar() { return araclar; } public static int getIlkBosYer() { return ilkBosYer; } } Kod 2.16 springornek/WEB-INF/src/ismantigi/Otopark.java Arac sınıfı sadece aracın plakasını tutmaktadır. Plakanın alt alanlarını(il kodu, harf kodu ve araç no) ayrı ayrı tutarak  girdi denetiminin daha kolay yapılmasını amaçlıyoruz. Uygulamamızda kaynak kodları karmaşıklaştırıp, şişireceği ve  okuyucunun uygulamayı çalıştırmasını zorlaştıracağı için bir veri tabanı kullanmayacağız.  Otopark  sınıfını bunun  boşluğunu doldurabilmek için ekliyoruz. Bu sınıfta park yerlerini ve buralara park eden araçları tutmak için bir Arac  dizisi kullanıyoruz ve araçların park yerlerinin dizideki tutuldukları dizinleri olmasını öngörüyoruz. Bu durumda boş  olan park yerlerine ilişkin dizinlerin değeri hiç bir araç bulunmadığına işaret edecek biçimde  null  olmaktadır. Bu  sınıfta  ilkBosYer  adlı   alan   da   anlaşılacağı   üzere   otoparkta   boş   durumda   olan   ilk   noktayı   göstermektedir.  Uygulamamızda kullanıcı isterse bundan daha farklı boş bir yeri seçebileceğinden dolayı  aracParket  yönteminin  içerisinde  bu değişken  sadece  bir  arttırılmak  yerine  otoparktaki  ilk  boş  yerin  bulunup  bu değerin  atanması  işlemi  gerçekleştiriliyor.   Eğer   otoparkta   boş   yer   kalmamışsa   bunu   belirtmek   için  ilkBosYer  değişkeninin   değeri  ­1  yapılıyor.

Ana Sayfa Uygulamamız için ilk olarak bir  ana sayfa yapalım. Bunu gerçekleştirmek için başlangıç amaçlı yazdığımız denetimci  sınıf ve JSP sayfasına benzer şekilde yeni bir denetimci ve  bir JSP sayfası ekleyebiliriz. Ana sayfada hangi park yerinde  hangi aracın bulunduğunu listeleyebiliriz ve yeni araç girişinin yapabileceği  sayfaya yönlendiren bir bağlantıya yer  vermemiz gerekir.  Amacımızı gerçekleştirebilmemiz için JSP sayfasının araçlar ve park yerleri bilgisine ihtiyacı vardır,  bu nedenle denetimci sınıfın döndürdüğü ModelAndView nesnesinin içine bu bilgiyi eklemesi gerekir (Kod 2.17).  package denetim; import ismantigi.Otopark; import import import import

javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse; org.springframework.web.servlet.ModelAndView; org.springframework.web.servlet.mvc.Controller;

public class AnasayfaDenetimci implements Controller { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {

}

ModelAndView mav = new ModelAndView("anasayfa"); mav.addObject("araclar", Otopark.getAraclar()); return mav;

} Kod 2.17 springornek/WEB-INF/src/denetim/AnasayfaDenetimci.java

Denetimci sınıfı (AnasayfaDenetimci), denetim paketinin içine koyuyoruz. Bu sınıf, daha önce verileri tutmak için  kullanacağımızı   belirttiğimiz  Otopark  sınıfının   araçları   ve   park   yerlerini   tuttuğu   diziyi,   geri   döndürdüğü  ModelAndView  nesnesine   ekliyor.   Bu   sınıfa   ilişkin   eklememiz   gereken   diğer   bir   nokta   da   görünümün  (view)  springornek/WEB­INF/jsp/anasayfa.jsp olarak belirtilmiş olmasıdır. Bu durumda, anas ayfa olarak kullanacağımız JSP  sayfasının adının anasayfa.jsp olması gerekiyor. Uygulamaya   eklediğimiz   yeni   denetimciyi   kullanabilmek   için   XML   yapılandırma   kütüğümüz   olan  springornek­ servlet.xml içinde tanımlamamız gerekiyor (Kod 2.18).  <property name="mappings"> <props> <prop key="/index.htm">anasayfaDenetimci                 <prop key="/basit.htm">basitDenetimci <property name="viewClass"> org.springframework.web.servlet.view.JstlView <property name="prefix">/WEB-INF/jsp/ <property name="suffix">.jsp Kod 2.18 springornek/WEB-INF/springornek-servlet.xml Görüldüğü gibi artık index.htm adresi yeni yazacağımız ana sayfayı görüntülemek üzere anasayfaDenetimci'ye  yönlendirilecek.  Kod   2.19'da  anasayfa.jsp'ye   yer   veriliyor.   Bu   sayfada  AnasayfaDenetimci'nin  araclar  anahtarı   ile  ModelAndView nesnesine eklediği araç dizisini JSTL etiketleri ve JSP EL sözdizim kurallarını kullanarak erişiliyor.  Bir döngüyle kılavuzun tüm elemanları geziliyor ve tüm park yeri numaralarına karşılık orada bulunan aracın plakası  listeleniyor, eğer araç bilgisi  null  değerine sahipse ilgili park yeri numarasına karşılık  Boş  ifadesi kullanılıyor. Bu  şekilde park numaralarının kullanımda olma durumu kullanıcı tarafından takibi kolaylaştırılıyor. Araç listesinin altında  ise   yeni   bir   araç   kaydının   yapılabilmesine   yönelik   bir   bağlantıya   yer   veriliyor.   Bu   bağlantının   adresi   olan  aracgiris.htm'yi daha ileride gerçekleştireceğiz. Şu anda araç ekleme sayfası aktif durumda olmadığı için tüm park  yerleri boş (null) durumda bulunuyor (Resim 2.3). <%@ page contentType="text/html; charset=ISO-8859-9" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> springornek

Spring MVC - Otopark Uygulaması



Araçlar

${i}. ${arac.ilKodu} ${arac.harfKodu} ${arac.aracNo} <em>Boş

">Araç Girişi Kod 2.19 springornek/WEB-INF/jsp/anasayfa.jsp

Resim 2.3 Ana Sayfa

Form Kullanımı Daha önce Spring MVC'nin farklı ihtiyaçlara cevap verebilecek nitelikte farklı denetimci sınıf seçenekleri sunduğundan  bahsetmiştik   ve   özellikle   formlar   içeren   sayfalarda   form   verilerinin   denetimi,   değerlendirilmesi   ve   kullanılması  konusunda kolaylıklar getiren form denetimci sınıfları vurgulamıştık. Uygulamamızda bunlardan çok kullanışlı olan ve  tüm   ihtiyaçlarımıza   cevap   veren  org.springframework.web.servlet.mvc.SimpleFormController  sınıfını kullanacağız. Örnekler üzerinde inceleyince daha iyi anlaşılacabilecek olmasına rağmen biraz daha derli toplu  biçimde   faydalı   olabileceği   için   aşağıda   bu   sınıfın   kullanımı   için   önemli   olan     bazı   noktalar   hakkında   özet   bilgi  verilmektedir.  SimpleFormController  sınıfı  formView  ve  successView  adlı iki nitelik içerir. Bunlara genellikle   XML 

yapılandırma   kütüğündeki   denetimci   tanımının  içerisinde   ilk  değer   ataması   yapılır.   Bu  niteliklerden  ilki   denetimci  tarafından denetlenecek olan formu içeren sayfaya ilişkin görünümün adıdır. Yani denetimciye yönelik bir istek geldiği  zaman doğrudan, kullanılacak olan formu içeren bu  görünüm görüntülenir . İkinci nitelik ise form işlemleri başarılı bir  şekilde sonuçlanırsa yönlendirilecek olan görünümü belirlemek üzere öngörülmüştür. Bu görünüm formView niteliği  örneğinde   olduğu   gibi   otomatik   olarak   görüntülenmez,   ancak   geliştirici   isterse   bu   nitelikle   belirlenen   görünüme  yönlendirme yapar (ModelAndView ile kullanarak). Aslında successView niteliğinin kullanımının tercih edilmesinin  nedeni değer atamasın XML içerisinde yapılabilmesi ve böylece gidilecek görünümün adının kodun içine gömülmesine  gerek kalmamasıdır. SimpleFormController'ın XML içinde ilklendirilebilen çok önemli iki niteliği daha vardır;  commandName  ve  commandClass. Bunları belirtmeden önce Spring MVC'deki komut  (command)  sınıflarının açıklanması gerekiyor.  Spring MVC, bir  formda kullanıcının   girdiği verilerin doğrudan bir Java nesnesinin (komut  nesnesi) nitelikleri ile  ilişkilendirilmesine (bağlama / bind)   sağladığı bir takım etiketler (tag) aracılığıyla izin verir ve bu sayede ilgili form  alanının içeriği nesnenin niteliğinin değeri olarak kaydedilir. Komut nesneleri adı verilen bu nesnelerin kullanımı, form  verilerinin   istek  (request)  nesnesinden   çıkartılıp   başka   bir   Java   nesnesine   kaydedilmesi   işini   geliştiricinin  yükümlülüğünden tamamen çıkartan çok pratik bir işlevdir. Ayrıca bu nesneler çeşitli amaçlara yönelik (örneğin verileri  doğrulama  (validation)) işlevlerde de Spring'in sağladığı yöntemler sayesinde doğrudan kullanılabilirler ve bu yapı  geliştiriciye çok önemli kolaylıklar sağlar. Sözünü ettiğimiz  commandName  ve  commandClass  nitelikleri de form  tarafından   kullanılacak   olan   komut  (command)  nesnesinin   adı   ve   sınıfıdır.   Bu   niteliklere   genellikle   yapılandırma  kütüğünde ilk değer atamaları yapılır. Eğer  commandName  niteliğine burada yer verilmezse komut nesnesinin adı  varsayılan olarak command olur ve nesneye görünümün içerisinden isimle erişim sağlanır. Komut nesnesinin sınıfını  belirten commandClass niteliği yapılandırma kütüğünde belirlenmişse ihtiyaç olduğunda otomatik olarak bu sınıftan  boş bir nesne oluşturulur ve kullanılır, buna alternatif bir çözüm ise denetimci sınıf içerisinde daha sonra açıklanacak  olan  formBackingObject  yöntemininin   yeniden   yazılmasıdır(override).   Komut   nesnesi   ile   ilgili   olarak  vurgulanması gereken diğer önemli bir nokta değerinin null olmasına izin verilmemesidir.    SimpleFormController  sınıfı   isteğin  (request)  değerlendirilip   yönlendirilmesi   sürecinin   farklı   noktalarında  otomatik olarak çağrılan ve  genellikle  bu sınıftan türetilen denetimci  sınıflar  tarafından yeniden yazılan  (override)  yöntemler içerir. Bunlardan önemli olan bazılarını kısaca özetleyelim: •

Object formBackingObject(HttpServletRequest); Formun komut nesnesinin yapılandırma kütüğünde  commandClass niteliği ile belirlenmesi durumunda bu   sınıfın   varsayılan   yapılandırıcısı   (default   constructor)   kullanılarak   bir   olgusunun   oluşturularak   formda  kullanıldığını   söylemiştik.   Bu   nitelik   belirtilmiş   olsun   veya   olmasın   denetimci   sınıfın   içinde   formBackingObject  yönteminin  yeniden yazılması   durumunda bu  yöntemin  döndürdüğü nesne   komut   nesnesi olarak kullanılır. Bu sayede, komut nesnesine bir takım ilk değerler vermek suretiyle (örneğin veri   tabanından gerekli veriler  çekilerek) bu verilerin formların ilişkilendirildikleri  (bağlandıkları) alanlarında   varsayılan olarak görüntülenmesi sağlanabilir. Burada dikkat edilmesi gereken, yöntemin geriye null değer   döndürmemesi şartıdır, aksi durumda bir çalışma zamanı hatası ortaya çıkar. Anlaşılacağı üzere bu daha form   görünümü görüntülenmeden önce çağrılan bir yöntemdir.



Map referenceData(HttpServletRequest); Bu yöntem komut nesnesinin içinde taşınması gereksiz olan verilerin görünüme iletilmesi amacıyla kullanılır.   Yani   formla   ilgisiz   olan   ama   görünüm     tarafından   (görüntülenmek   amacıyla)   kullanılacak   olan   verilerin   iletilmesini   sağlar.   Doğrudan  Controller'dan   türetilen   denetimcilerin  handleRequest  yönteminde  ModelAndView  nesnesine verileri eklemesine benzetilebilir. Yöntemin döndürdüğü Map nesnesindeki tüm   veriler yine bu nesnedeki anahtar sözcükleri kullanılarak görünüme (formView) geçirilirler. Yine anlaşılacağı   üzere form görünümü görüntülenmeden önce çağrılan bir yöntemdir.



ModelAndView  onSubmit(HttpServletRequest,HttpServletResponse,Object,BindException); Bu yöntem yeniden yazılması olmazsa olmazlardan biridir ve formdan bir submit isteği geldiğinde yapılması   gerekenleri gerçekleştirildiği ve işlem sonucunda gidilmesi gereken sayfaya yönlendirmenin yine döndürülen   ModelAndView  nesnesi sayesinde yapıldığı   yöntemdir. Form işlemlerinin tamamen sonuçlandığı yöntem   olduğu söylenilebilir.

Bir   form   denetimci   tarafından   formun   ele   alınmasına   ilişkin   akışla   ve   sağlanan   diğer   yöntemlerle   ilgili   detaylı  açıklamaları Spring kurulumunuzun  docs/api  kılavuzunun altında bulunan  javadoc  belgelerinde bulabilirsiniz. Bunun  yanısıra, bu belgeleri geliştirme sırasında önemli bir başvuru kaynağı olarak kullanabilirsiniz.

Araç Girişi Yeni bir aracın otoparka girişinin gerçekleştirildiği sayfa aracın plakasına ilişkin üç alanın girilmesine ve uygun bir park  yerinin seçilmesine olanak veren bir form içermelidir. İşlem gerçekleştirildikten sonra, verilerde bir hata yoksa, listenin  son durumunu görmek üzere tekrar ana sayfaya dönülmesini öngörüyoruz. Bir form denetimcisi yazmadan önce komut  sınıfını yazalım. Bu arada komut sınıfları için komut adlı bir paket oluşturduğumuza dikkat edin (Kod 2.20).  Form   üzerinde   araca   dair   bilgilerle   (örneğimizde   sadece   plaka   alanları)   aracın   otoparkta   hangi   park   yerine   park  edildiğine dair bilgiler girileceği için komut sınıfımızda (AracGirisi) bir Arac nesnesi ve park yeri için bir tam sayı  bulunuyor. Tabi bu sınıfın komut sınıfı olarak kullanılabilmesi için niteliklerine okuma ve yazma izni veren JavaBean  tanımına uygun erişim yöntemleri (set/get) gerçekleştirilmelidir. package komut; import ismantigi.Arac; public class AracGirisi { Arac arac; int parkYeri; public Arac getArac() { return arac; } public void setArac(Arac arac) { this.arac = arac; } public int getParkYeri() { return parkYeri; } public void setParkYeri(int parkYeri) { this.parkYeri = parkYeri; } } Kod 2.20 springornek/WEB-INF/src/komut/AracGirisi.java Kod 2.21'de araç girişi sayfasını ele almakta kullanacağımız  AracGirisFormDenetimci  sınıfına yer verilmiştir.  Bu sınıfta daha önce sözünü ettiğimiz üç yönteme de yer verildiğini görüyoruz.  package denetim; import ismantigi.Otopark; import komut.AracGirisi; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import import import import

org.springframework.validation.BindException; org.springframework.web.servlet.ModelAndView; org.springframework.web.servlet.mvc.SimpleFormController; org.springframework.web.servlet.view.RedirectView;

public class AracGirisFormDenetimci extends SimpleFormController { protected ModelAndView onSubmit( HttpServletRequest request, HttpServletResponse response, Object command, BindException errors)

throws Exception { AracGirisi aracGirisi = (AracGirisi)command; Otopark.aracParket(aracGirisi.getArac(), aracGirisi.getParkYeri()); return new ModelAndView(new RedirectView(getSuccessView()));

}

protected Map referenceData(HttpServletRequest request) throws Exception { Map veri = new HashMap(); veri.put("araclar", Otopark.getAraclar()); return veri;

}

protected Object formBackingObject(HttpServletRequest request) throws Exception { AracGirisi aracGirisi = new AracGirisi(); aracGirisi.setArac(new Arac()); aracGirisi.setParkYeri(Otopark.getIlkBosYer()); return aracGirisi; }

} Kod 2.21 springornek/WEB-INF/src/denetim/AracGirisFormDenetimci.java

Bu yöntemlerden formBackingObject yöntemi komut sınıfı olan AracGirisi sınıfının nesnesini oluşturduktan  sonra ilk değer atamaları yapmak amacıyla gerçekleştirilmiştir. Oluşturulan yeni AracGirisi nesnesinin parkYeri  niteliğinin   değeri  Otopark  sınıfının  ilkBosYer  niteliğinin   değeri   ile   kurulmaktadır.   Böylece   JSP   sayfasında  varsayılan   olarak   bu   değerin   kullanıcıya   sunulması   sağlanacaktır   ve   kullanıcı   isterse   sadece   plaka   alanlarını  doldurmakla yetinecek ve uygun park yeri seçimi yapmasına gerek kalmayacaktır.  Yeniden yazılan diğer bir yöntem olan  referenceData  yöntemi ise form görünümünün ihtiyacı olan araç park  yerleri   verisinin   gönderilmesi   amacı   gütmektedir.   Görünüme   yine  Otopark  sınıfında   tutulan   araç   dizisi  gönderilmektedir. Bu bilgi görünüm tarafından, kullanıcıya kolaylık sağlamak amacıyla, park yerlerini bunlardan dolu  veye boş olanları ayırt edilebilecek biçimde farklı renklerde sunmak amacıyla kullanılacaktır. Son olarak onSubmit yöntemi form üzerinde ilgili düğmenin tıklanarak araç girişi olayının tetiklenmesi ile çağrılır.  Bu yönteme gelen argümanlardan birinin Object türündeki command nesnesi olduğunu görüyoruz. Bu nesne, formda  kullanılan komut nesnesidir ve ileride JSP sayfasını incelerken göreceğimiz üzere forma girilen verilerle araç ve park  yeri   niteliklerinin   değerleri   kurulmuş   olarak   bu   yönteme   gelir.   Komut   nesnesi  Otopark  sınıfının   araç   girişini  kaydetmek amacıyla kullanılan aracParket yönteminin ihtiyacı olan araç ve park yeri verilerini sağlar. Gerçek bir  uygulamada   bunun   yerine   örneğin   bir   veri   tabanı   güncellemesi   yapılabilirdi.   Geri   döndürülen  ModelAndView  nesnesine herhangi bir veri eklenmezken, bu nesnedeki görünümün successView niteliği ile belirlendiği görülüyor,  bu   niteliğin   değeri   daha   önce   söz   edildiği   gibi   yapılandırma   kütüğünde   kurulması   öngörülmektedir.  SimpleFormController'dan   türeyen   sınıflar   için   bile   bu   niteliğe   doğrudan   erişim   izni   olmadığı   için  getSuccessView yöntemi kullanılmaktadır.

RedirectView Kod   2.21'de   görünümün   doğrudan   görünüm   adı   ile   belirtilmesi   yerine   görünüm   adı   ile   oluşturulan   bir  RedirectView  nesnesinin kullanıldığını görüyoruz. İlk kullanımda (görünüm adı kullanımı) isteğin  (request)  kontrolü aynen  başka bir noktaya yönlendirilir veya devredilir (forward). Bu durumda eğer post yöntemini kullanan  bir form   bu şekilde yönlendirilmişse kullanıcı sayfayı her yenilediğinde aynı istek tekrar işletilir. Daha açık bir  ifade ile kullanıcı ekranında artık form değil örneğin işlem sonucunu yansıtan bir sayfa vardır, ancak kullanıcı  sayfayı yenilediği zaman üretilen istek form tarafından oluşturulan isteğin aynısıdır ve bu ­ genellikle istenmeyen bir  şekilde ­ bir kez gerçekleştirilmesi gereken bir işlemin tekrar edilmesine neden olur. Kritik bir uygulamada bu  önemli   sakıncaları   olabilir.   Yeniden   yönlendirme  (redirect)  yaklaşımının   kullanılması   ile   yönlendirilen   sayfaya  gidilirken   belirtilen   url'ye   tamamen   yeni   bir   istek   oluşturularak   yönlendirme   gerçekleşir.   Yani   form   tarafından  üretilen istekten tamamen bağımsız yeni bir istek oluşturularak yeni sayfaya gidilir. Bu kullanımda dikkat edilmesi 

gereken   nokta   yönlendirme   bir   görünüm   adı   ile   değil     görünüme   ilişkin   adres   ile   yapılır   ve  successView  niteliğinin değerinin bu göz önüne alınarak belirlenmesi gerekir.  

Sonuç   olarak,   yapılandırma   kütüğünde  AracGirisFormDenetimci  için   eklenilen   tanımlamaları   Kod   2.22'de  görebilirsiniz.   İlk   olarak  aracGirisFormDenetimci  adıyla   tanımladığımız   denetimciyi   url   eşleme   kısmında  aracgiris.htm  adresi   ile   eşleştirildiğini   vurgulayalım   (ana   sayfanın   en   altında   bulunan   bağlantıyı   hatırlayın!).   Bu  denetimci tanımının içinde komut nesnesinin adının  aracGiris  olduğu ve bunun  AracGirisi  türünde olduğu  görülüyor. Ayrıca formun aracgiris.jsp içerisinde bulunduğu, dolayısıyla bu denetimciye yönelik istekler geldiğinde bu  sayfanın görüntülenmesi talebi belirtiliyor. Son olarak  successView  niteliği ile form işlemleri başarılı bir şekilde  tamamlandığında   yeniden   yönlendirmenin  (redirect)  yapılacağı   adresin   bu   XML   kütüğü   içerisinde   belirlendiğini  görüyoruz. <property name="sessionForm">true <property name="commandName">aracGirisi <property name="commandClass"> komut.AracGirisi <property name="formView">aracgiris <property name="successView">index.htm <property name="mappings"> <props> <prop key="/index.htm">anasayfaDenetimci <prop key="/basit.htm">basitDenetimci <prop key="/aracgiris.htm">aracGirisFormDenetimci <property name="viewClass"> org.springframework.web.servlet.view.JstlView <property name="prefix">/WEB-INF/jsp/ <property name="suffix">.jsp Kod 2.22 springornek/WEB-INF/springornek-servlet.xml Şimdi sıra aracgiris.jsp'yi gerçekleştirmeye geldi. Bu sayfada komut nesnesi niteliklerini form alanlarına bağlayabilmek  (bind)  için Spring'in etiket kütüphanesini kullanmamız gerekiyor, bunun için de yapılması gereken bir kaç küçük iş  bulunuyor. Önce etiket kütüphanesi tanımlayıcısı kütüğü olan  spring.tld  kütüğünü kurulumunuzun  dist  kılavuzunun  altından   (örneğin   benim   için  spring­framework­1.2.5/dist/spring.tld)   uygulamanızın  WEB­INF  kılavuzunun   içine 

kopyalayın. Uygulamanın bu kütüphanenin kullanımına izin vermesi için web.xml kütüğüne de bir ekleme yapmamız  gerekiyor (Kod 2.23). Artık bu etiket kütüphanesini bir JSP içerisinde kullanabilmek için tek satırlık bir   kod yeterli  olacaktır (taglib directive). Artık Kod 2.24'te verilen aracgiris.jsp'yi uygulamaya ekleyip yeniden çalıştırabilir ve sonucu  aracgiris.htm adresinde görebilirsiniz (Resim 2.4). <web-app version="2.4"> <servlet> <servlet-name>springornek <servlet-class> org.springframework.web.servlet.DispatcherServlet 1 <servlet-mapping> <servlet-name>springornek *.htm <welcome-file-list> <welcome-file>index.jsp /spring /WEB-INF/spring.tld Kod 2.23 springornek/WEB-INF/web.xml <%@ page contentType="text/html; charset=ISO-8859-9" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="spring" uri="/spring" %> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> springornek - Araç Girişi

Spring MVC - Otopark Uygulaması

Araç Girişi



Araç Plakası: <spring:bind path="aracGirisi.arac.ilKodu"> <spring:bind path="aracGirisi.arac.harfKodu"> <spring:bind path="aracGirisi.arac.aracNo">
Park Yeri: <spring:bind path="aracGirisi.parkYeri"> <select name="${status.expression}">
">Ana Sayfa Kod 2.24 springornek/WEB-INF/jsp/aracgiris.jsp Gördüğünüz gibi sayfa plakanın ve park yerinin girilmesi için alanlar ve submit türünde, araç girişinin kaydedilmesini  tetikleyen   bir   düğmeyi   içermekte.   Dikkat   ettiyseniz  form  etiketinin   içinde   herhangi   bir  action  niteliğine   yer  verilmemiştir, çünkü form zaten tamamen denetimcinin kontrolündedir ve düğmenin tıklanması halinde ne yapılması  gerektiği de denetimci tarafından belirlenir (onSubmit yönteminin çalıştırılması gibi).   Aslında bu JSP sayfasında  spring:bind  etiketileri ve bunların içinde kullanılan  status  adlı değişken dışında  yenilik bulunmuyor. Plaka alanları text türündeki input alanlarından oluşuyor, park yeri numaraları ise bir select  etiketi   ile   görüntüleniyor.   Park   yeri   numaraları   JSTL  forEach  etiketi   kullanılarak   araclar   adlı   (denetimcinin  referenceData yöntemini hatırlayınıız) liste üzerinde dolaşırken sayaç olarak kullanılan bir i değişkeni ile select  etiketinin   içerisine   bu   park   numarasına   ilişkin  option  etiketi   ekleniliyor.   Araç   listesinin   kullanımı   ise  option  etiketinin içeriği dikkatli incelenirse sıradaki aracın değeri null değilse – yani o park yeri dolu ise – bu seçeneğin gri  renkte görüntülenmesi amacını taşıyor.  Daha önce söz ettiğimiz bağlama işlemi spring:bind etiketi ile gerçekleştiriliyor. Bu etiketi kullanmak için  <%@ taglib prefix="spring" uri="/spring" %> satırını eklemeyi unutmamanız gerekiyor. İsterseniz bu etiketin kullanımını satır satır inceleyelim.  <spring:bind path="aracGirisi.arac.ilKodu"> satırı bağlamanın başlangıcıdır ve path niteliği ile ilgili form alanının komut nesnemiz olan aracGirisi'nin arac  değişkeninin ilKodu niteliği ile bağlanacağını ifade ediyoruz.  Input etiketi ile il kodunun girilebilmesi için 30 piksel genişliğinde text türünde bir alan tanımı yapıyoruz. Bu alanın  adının   ve   değerinin   belirlenmesinde  status  değişkeninin   kullanıldığını   görüyoruz.   Bu   değişken  bind  etiketinin  içerisinde  Spring  tarafından  tanımlanan  bir  değişkendir  ve  expression  ve  value  ile   örneklediğimiz   bir  takım  nitelikler sağlar. Bunlardan expression çoğunlukla form alanının isimlendirmede kullanılan bir deyimi ifade eder.  Genelde   değeri   komut   nesnesinin   bağlanılan   niteliğinin   adıdır,   mesela   örneğimizde  arac.ilKodu    değerine   sahip  olacaktır. Bu şekilde, geliştiricinin kendisinin belirleyeceği form alanı isimlerini daha sonra istek (request) nesnesinden  verileri parametreler olarak çıkartırken hatırlaması zorunluluğu ortadan kalkmış oluyor. 

Kullandığımız   diğer   nitelik   olan  value  ise   form   alanına   bir   değer   vermekte   kullanılıyor.   Bu   niteliğin   önemini  kavramak için bir veri güncelleme sayfası düşünelim. Genelde veri güncelleme sayfalarında alanlara ilişkin daha önce  girilmiş olan verilerin görüntülenmesi gerekir. Bunu gerçekleştirmek için ise daha çok eski verileri sayfaya parametre  olarak göndermek, bu verilerin değerinin  null  veya anlamsız olup olmadığı kontrolünü yapmak ve sakıncası yoksa  form alanlarının değeri olarak bu değerleri kullanmak gibi kodu gerçekten kabartan ve anlaşılmaz hale getiren eklemeler  yapmamız gerekir. Tüm bu sorunları açıklamaya çalışığımız value niteliğinin yukarıdaki gibi kullanımı çözmektedir.  Çünkü status.value değişkenine otomatik olarak komut nesnesinin ilgili niteliğinin değeri koyulur. İlk olarak artık  bu   veriyi   sayfaya   parametre   olarak   gönderme   ihtiyacı   ortadan   kalkar,   çünkü   zaten   elimizde   olan   komut   nesnesi  kullanılmaktadır. Diğer bir gelişme ise artık böyle bir parametrenin var olup olmadığı  varsa değerinin  null  olup  olmadığı kontrolüne gerek kalmaz. Çünkü bu kullanımda değerin  null  olup olmadığı Spring tarafından denetlenir,  eğer değilse bu değer ilgili alanda görüntülenir. Bu satır bind etiketinin sonlandığı noktadır ve bağlama işlemi için gereken kod tamamlanmıştır. Bağlama işlemi ile  birlikte formdan submit isteği üretildiği zaman form alanındaki değer komut nesnesinin ilgili niteliğinin değeri olarak  kurulur  ve komut nesnesine erişilen her yerden bu değere erişilir. Görüldüğü gibi artık örneğin form verisi kullanılarak  veri tabanında yapılacak bir güncelleme için istek nesnesinin parametrelerini almak ve değişkenlerin içerisine koymak  için satırlarca kod yazmanıza gerek yok. Çünkü her şey gereken komut nesnesinin içine yerleşmiş durumdadır.  Bunu  zaten denetimcinin onSubmit yönteminin içerisindeki  Otopark.aracParket(aracGirisi.getArac(), aracGirisi.getParkYeri()); satırı ile örneklemiştik. Diğer ilginç ve güzel bir örnek de select alanını çevreleyen bind etiketinin kullanımıdır. Bu sefer komut nesnesinin  parkYeri  alanını  select  etiketi ile bağlıyoruz ve bu değer sonuç olarak seçilen değerle kuruluyor. Daha önce  güncelleme sayfalarında görebileceğimizden söz ettiğimiz eski (veya varsayılan) değerin sayfada yüklenmesini de
Resim 2.4 Araç Girişi Sayfası

Doğrulama (Validation) Lütfen plakanın il kodu veya araç alanına bir tam sayı olmayan bir değer girerek veya boş bırakarak araç girişi yapmayı  deneyin. İşlemin tamamlanamadığını ana sayfa yerine araç girişi sayfasında kaldığınızı görerek anlamış olmalısınız. Bu  Spring   tarafından   otomatik   olarak   yapılan,   beklenilen   veri   türü   (tamsayı)   ile   girdinin   veri   türünün   uyuşmaması  nedeniyle işlemin gerçekleştirilmesine izin vermeyen veri doğrulaması (validation) nedeniyle olmuştur. Yukarıda   açıklanan   işlev   aslında   geliştiriciyi   bir   çok   zahmetten   kurtarmaktadır.   Çünkü   form   verilerinin   türlerinin  kontrol edilmesi, dönüştürme sırasında fırlatılan aykırı durumların ele alınması ve kullanıcıya bu hatanın sonucu ile geri  dönülmesi gibi hacim kaplayan bir çok kodlama işlemlerinin otomatikleşmesi sağlanıyor.  Ancak biraz düşününce bunların yeterli olmadığı açıktır. Bir uygulamada iş mantığı veya veri tutarlılığı gibi bir çok  konuda   farklı   denetimler   gerekebilir,   ayrıca   bu   denetimler   sonucu   fark   edilen   hataların   giderilmesi   veya   tekrar  edilmemesi için kullanıcıya mutlaka geri bildirimde bulunulması gerekmektedir. Tabi Spring'in hata denetimi desteği de  bu kadarla kalmamakta, sözü edilen iki konuyla ilgili etkili çözümler sunulmaktadır. Spring'in MVC kısmından bağımsız olan org.springframework.validation paketi veri doğrulama işleminde  kullanılır. Bu paketin içindeki  Validator arayüzünden türetilen ve parametre olarak aldığı komut nesnesi üzerinde  doğrulama   işlemlerini   yerine   getirebildiği  validate  yöntemini   gerçekleştiren   sınıfların   nesneleri   bir   form  denetimcisinin validator niteliği olarak kullanılabilir. Tahmin ettiğiniz gibi bu tanımlamalar doğrulama yapan sınıf  yazıldıktan sonra yapılandırma kütüğü üzerinde gerçekleştirilir. Kendi uygulamamızı göz önüne aldığımızda tür denetiminin dışında mantıksal denetimler yapmamız gerektiği açıktır.  Bunları şu şekilde listeleyebiliriz: •

Plakanın il kodu kesimi 1 – 81 (Ocak 2006 itibarı ile) arasında bir tamsayı olmalıdır. 



Plakanın araç numarası kesimi 1 – 9999 aralığında bir tamsayı olmalıdır.



Plakanın harf kodu kesimi ise 1 – 3 adet (büyük) harften ibaret olmalıdır.



Dolu bir park yerine başka bir araç park edilemez.

Uygulamamızda veri doğrulama amaçlı sınıflarımızı koyabileceğimiz  dogrulama  paketini oluşturduktan sonra Kod  2.25'te verilen ve bu kontrolleri gerçekleştiren Validator türevi sınıfı buraya kaydedebilirsiniz. package dogrulama; import ismantigi.Otopark; import komut.AracGirisi; import org.springframework.validation.Errors; import org.springframework.validation.Validator; public class AracGirisDogrulayici implements Validator { public boolean supports(Class c) { return c.equals(AracGirisi.class); } public void validate(Object command, Errors errors) { AracGirisi aracGirisi = (AracGirisi)command; if(Otopark.doluMu(aracGirisi.getParkYeri())) errors.rejectValue("parkYeri", "parkYeriDolu"); if(aracGirisi.getArac().getIlKodu() < 1 || aracGirisi.getArac().getIlKodu() > 81) errors.rejectValue("arac.ilKodu", "gecersizIlKodu"); if(aracGirisi.getArac().getHarfKodu().length() > 3) errors.rejectValue("arac.harfKodu", "harfKoduUzunlukHatasi"); if(!aracGirisi.getArac().getHarfKodu().matches("[A-Z]*"))

errors.rejectValue("arac.harfKodu","harfKoduKarakterHatasi");

}

if(aracGirisi.getArac().getAracNo() < 1 || aracGirisi.getArac().getAracNo() > 9999) errors.rejectValue("arac.aracNo", "gecersizAracNo")

} Kod 2.25 springornek/WEB-INF/src/dogrulama/AracGirisDogrulayici.java İsterseniz bu kodu ele almadan önce doğrulama amalı sınıfımızın tanımlanıp  AracGirisDenetimci  ile bağlama  etiketlerini eklememiz  gereken yapılandırma kütüğünün son durumunu görüp doğrulamanın nasıl gerçekleştirildiğini  açıklığa kavuşturalım (Kod 2.26). <property name="sessionForm">true <property name="commandName">aracGirisi <property name="commandClass">komut.AracGirisi <property name="validator"> <property name="formView">aracgiris <property name="successView">index.htm <property name="mappings"> <props> <prop key="/index.htm">anasayfaDenetimci <prop key="/basit.htm">basitDenetimci <prop key="/aracgiris.htm">aracGirisFormDenetimci <property name="viewClass"> org.springframework.web.servlet.view.JstlView <property name="prefix">/WEB-INF/jsp/ <property name="suffix">.jsp <property name="basename">mesajlar Kod 2.26 springornek/WEB-INF/springornek-servlet.xml Yapılandırma   kütüğünde   görüldüğü   gibi   öncelikle   doğrulayıcı   sınıf   için   bir   çekirdek  (bean)  tanımlanıyor 

(aracGirisDogrulayici). Sonra bu doğrulayıcı aracGirisDenetimci'nin validator niteliği tarafından işaret  ediliyor. Dikkat ederseniz doğrudan bir değer vermek yerine çekirdeğe işaret edildiği için ref etiketi kullanılıyor. Artık  form denetimcinin bir doğrulayıcısı vardır ve formdan bir submit isteği geldiğinde öncelikle bu doğrulayıcının validate  yöntemi çağrılır ve sonuç olarak bir hata belirlenmişse istek geri çevrilerek form tekrar görüntülenir (ve sakıncası yoksa  ­şifre alanı vs. değilse­ kullanıcı tarafından  girilmiş olan veriler gösterilir).  Şimdi   doğrulayıcı   sınıfın   içeriğini   tartışabiliriz.   Bu   sınıfta   gerçekleştirilen   ilk   yöntem  supports  yöntemidir.   Bu  yöntem doğrulayıcıya verilen bir komut nesnesinin bu doğrulayıcı tarafından ele alınıp alanıamayacağını belirlemek için  kullanılır.   Onun   için   hemen   her   doğrulayıcı   bu   yöntemin   içeriğini   aynı   şekilde   fakat   farklı   bir   komut   sınıfı   ile  gerçekleştirir. Diğer yöntem olan  validate'in iki argümanı vardır. Bunlardan  Object  tütündeki  command  komut nesnesidir ve  görüldüğü gibi biz onu  AracGirisi  türüne çevirerek kullanıyoruz. Diğer argüman ise form üzerinde ortaya çıkan  hataların tutulduğu errors nesnesidir. Bu nesnenin içeriği sadece bu yöntem tarafından belirlenmez, daha önce söz  ettiğimiz gibi Spring'in otomatik olarak gerçekleştirdiği denetimlerle bulunan hatalar da bu nesnenin içinde bulunur.  sonuç olarak bu nesneye kaydedilmiş hata(lar) varsa  submit  işlemi gerçekleştirilmez ve form yeniden görüntülenir.  Yöntemin içerisinde yukarıda listelenen, iş mantığına dair bir takım kontroller yapılıyor ve eğer hatalı bir durum varsa  bu errors nesnesinin içerisine  rejectValue yöntemi çağrılarak ekleniyor. Bu yönteme verilen iki parametreden  ilki komut nesnesinin hataya sebep olan niteliğinin adıdır. İkincisi ise ortaya çıkan hataya ilişkin kullanılan bir anahtar  kelimedir. Bu anahtar örneğin görüntülenecek hata mesajının belirlenmesinde kullanılabilir.   Spring'in ilgili javadoc  belgeleri incelenirse  Errors   ve  ValidationUtils  sınıflarının sağladığı kullanışlı bir takım yöntemlerin daha  bulunduğu görülebilir. Mesaj konusuna değinmişken yapılandırma kütüğüne eklediğimiz bir diğer çekirdek (bean) olan messageSource'a  değinmemiz   gerekiyor.   Bu   aslında   Spring   çatısının   yine   MVC'den   bağımsız   olarak   sağladığı   bir   çözümdür   ve  org.springframework.context.support.ResourceBundleMessageSource  sınıfının   bir   nesnesidir.  Burada bu işlevin sadece konumuz kapsamında, örneğimiz içindeki kullanımına yer vereceğiz. Çekirdek tanımında yer  alan  basename  niteliğine   görüldüğü   gibi  mesajlar  değeri   atanıyor.   Bu   tanım   uygulamada   mesajların  mesajlar.properties adlı kütüğün içinde bulunduğunu ifade eder. Kısaca açıklamak gerekirse (uzantısı .properties olan)  properties kütükleri  her satırda birbirinden “=” işareti ile birbirinden ayrılan anahtar değer çiftlerinden oluşan, sade ve  pratik bir şekilde bu değerleri kaynak kodun içerisine gömülmekten kurtaran bir çözümdür ve sadece Spring tarafından  değil Java tarafından her tür uygulamada kullanımı desteklenen bir standarttır. Biz içeriğini Kod 2.27'de görebileceğiniz  mesajlar.properties  kütüğünü  /WEB­INF/classes  kılavuzunun   altına   koyuyoruz   ve   yapılandırma   kütüğündeki   tanım  sayesinde Spring tarafından anahtar kelimelere karşılık gelen mesajları içeren  mesajKaynağı(messageSource)  olarak  algılanmasını   sağlıyoruz.     Dikkat   edilmesi   gereken   bir   nokta   standartlar   gereği   bu   kütükte   yer   alan   bazı   Türkçe  karakterlerin   algılanamaması   nedeniyle   onlara   Unicode   değerleri   ile   yer   veriyoruz  (İ=\u0130,   ı=\u0131,   Ş=\u015E,  ş=\u015F, Ğ=\u011E, ğ=\u011F). typeMismatch=Geçersiz veri! typeMismatch.ilKodu=\u0130l kodu bir tamsay\u0131 olmal\u0131! typeMismatch.aracNo=Araç no bir tamsay\u0131 olmal\u0131! parkYeriDolu=Seçti\u011Finiz park yeri dolu! gecersizIlKodu=\u0130l kodu 1-81 aras\u0131nda olmal\u0131! harfKoduUzunlukHatasi=Harf kodu en fazla 3 karakter içerebilir! harfKoduKarakterHatasi=Harf kodu yaln\u0131z A..Z aras\u0131ndaki karakterleri içerebilir! gecersizAracNo=Araç no 1-9999 aras\u0131nda olmal\u0131! Kod 2.27 springornek/WEB-INF/classes/mesajlar.properties Burada söz edilmesi gereken bir nokta da Spring tarafından tanımlanan  typeMismatch  anahtarıdır. Kod 2.27'de  bizim   belirlediğimiz   anahtarlardan   biri   olmayan   bu   anahtar   bir   tür   dönüşümü   hatası   ortaya   çıktığı   zaman   Spring  tarafından üretilir.  typeMismatch  tek başına tüm tür dönüşümü hatalarına karşılık gelirken, istenirse niteliğe özel  hata mesajlarına yer verebilmek için typeMismatch.ilKodu örneği gibi bir kullanım tercih edilebilir.  Komut nesnesini kullanarak veri denetimini nasıl yapabileceğimizi gördük. Hataların kullanıcıya bildirilmesinde ise  yine   Spring   etiketlerine   başvuracağız.   Biz   örneğimizde  spring:bind  etiketinin   yanısıra  spring:hasBindErrors etiketini kullanarak hata geri bildirimini örnekleyeceğiz. Örneğimizde yer almayacak olsa  da  hasBindErrrors'un   sağladığı  errors  değişkeninin   (bind  etiketinin  status  değişkeninin   bir   benzeri)  errorCount, allErrors gibi niteliklerinin de faydalı kullanımları olabileceğini hatırlatmak gerekir. Tüm Spring  etiketleri   hakkında   detaylı   bilgi   için   Spring   kurulumunuzun  docs/taglib  kılavuzu   altındaki   belgelerden  yararlanabilirsiniz. Şimdi biz üzerine bazı eklemeler yaparak geliştirdiğimiz  aracgiris.jsp'de kullanıcıya yönelik hata 

bildirimini nasıl ele aldığımızı görelim (Kod 2.28). <%@ page contentType="text/html; charset=ISO-8859-9" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="spring" uri="/spring" %> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9"> springornek - Araç Girişi

Spring MVC - Otopark Uygulaması

Araç Girişi

Araç Plakası: <spring:bind path="aracGirisi.arac.ilKodu"> <spring:bind path="aracGirisi.arac.harfKodu"> <spring:bind path="aracGirisi.arac.aracNo"> <spring:bind path="aracGirisi.arac.*">
${error}
Park Yeri: <spring:bind path="aracGirisi.parkYeri"> <select name="${status.expression}">
${error}


<spring:hasBindErrors name="aracGirisi">
Lütfen hatalı girişleri düzeltiniz!
">Ana Sayfa Kod 2.28 springornek/WEB-INF/jsp/aracgiris.jsp Görüldüğü gibi plaka alanlarına dair hataların listesi tablonun plaka alanlarının bulunduğu hücresinde, park yerine dair  hata mesaj(lar)ı da park yerine dair hücrede görüntüleniyor. Hata mesajlarını göstermede  bind  etiketinin sağladığı  status  değişkeninin   daha   önce   söz   etmediğimiz  errorMessages  niteliğinden   yararlanıyoruz.   Bu   nitelik   liste  türündedir ve mesajlar bu liste üzerinde dolaşılarak görüntülenir. Plaka alanlarına ilişkin hataların görüntülendiği      <spring:bind path="aracGirisi.arac.*">                      
${error}                   kısımda   komut   nesnesinin   ara   niteliğinin  tüm   niteliklerine  (arac.*;  plaka  alanları)  dair  bir   bağlama  (bind)  işlemi  yapılıyor. Buradaki komut nesnesi niteliklerini herhangi bir form alanına bağlama işlemi yoktur, sadece onlara ilişkin  hata mesajlarına erişebilmek amacı güdülmektedir. Park yeri seçimi ile ilgili hatalar ise                  
${error}      satırları ile görüntüleniyor. Dikkat ederseniz burada yeni bir  bind  etiketi kullanılmıyor, çünkü  parkYeri  niteliğini  form   alanı   ile   bağlamak   için   açılan   etiket   henüz   kapatılmadı   ve   varsa   ona   ilişkin   hatalara   burada  status.errorMessages üzerinden erişilebiliyor. Son olarak  <spring:hasBindErrors name="aracGirisi">
Lütfen hatalı girişleri düzeltiniz!
satırlarında hasBindErrors etiketinin sanki bir if deyimi gibi davranarak, komut nesnesinin herhangi bir niteliği için  girdi hatası bulunmuşsa bunların giderilmesini öneren bir mesaj görüntülenmesinde kullanımı örneklenmektedir. Resim  2.5'te hata geri bildirimine ilişkin bir örnek ekran görüntüsü bulunmaktadır.

Resim 2.5 Veri Doğrulama ­ Hata Geri Bildirimi

Durdurucular (Interceptors) Durdurucu kavramı Spring'in işleyici eşleme  (handler mapping)  mekanizması ile birlikte düşünülen bir işlevdir. Bir  isteği   uygun   denetimciye   yönlendiren   işleyici   eşleme   nesnesinin  (handler   mapping)  içerisinde  org.springframework.web.servlet.HandlerInterceptor  arayüzünü   gerçekleştiren   durdurucu  sınıflarının   nesneleri   bulunabilir.   Bu   arayüz  preHandle,  postHandle  ve  afterCompletion  yöntemlerini  sağlar. Bunlardan preHandle uygun denetimci çalıştırılmadan önce, postHandle denetimci çalıştırıldıktan sonra,  ama görünüme yönlendirilmeden önce, afterCompletion ise istek tamamen gerçekleştirildiğinde çağrılır. Uygulamamızda   durdurucuları   örneklemek  için   otoparkta   yeni   araç   girişi   için   boş  yer   kalmadığı   zaman  araç  giriş  sayfasına   gelen   isteklerin   değerlendirilmeden   ana   sayfaya   yönlendirilmesi   senaryosunu   ön   görüyoruz.   Bu   durumda  durdurucunun işlemleri preHandle yönteminin içinde gerçekleştirmesi gerektiği ortaya çıkıyor. Çünkü bir denetimci  (aracGirisFormDenetimci)   çalıştırılmadan   önce   onun   çalıştırılıp   çalıştırılamayacağınca   karar   verilmesi   söz  konusu. Ancak burada ortaya çıkan bir problem daha var; tüm denetimciler aynı işleyici eşleme nesnesi tarafından ele  alındığı için tüm denetimcilere gelen istekler durdurucu tarafından park yeri kalıp kalmadığı sorgusuyla karşı karşıya  kalacaklardır.   Bunu   çözebilmek   için   içerisinde   sadece  aracGirisDenetimci'sinin   eşlemesinin   ve   durdurucu  tanımının yer aldığı yeni bir işleyici eşleme tanımına ihtiyacımız olacaktır. Kod 2.29'da durdurucu sınıfın içeriğine yer  verilmiştir. package denetim; import ismantigi.Otopark; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;

public class AracGirisDurdurucu implements HandlerInterceptor { protected String hataSayfasi; public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if(Otopark.doluMu()) { response.sendRedirect(hataSayfasi); return false; } return true; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } public String getHataSayfasi() { return hataSayfasi; }

}

public void setHataSayfasi(String hataSayfasi) { this.hataSayfasi = hataSayfasi; } Kod 2.29 springornek/WEB-INF/src/denetim/AracGirisDurdurucu.java

Gördüğünüz gibi  preHandle  yönteminin içerisinde  Otopark  sınıfının  doluMu  yöntemi çağrıılıyor ve otoparkın  dolu olup olmadığı denetleniyor. Eğer dolu ise araç giriş sayfasını görüntüleyecek olan denetimci çalıştırılmamalıdır, bu  nedenle geriye false döndürülmektedir. Tabi denetimcinin çalıştırılmaması durumunda görüntülenecek olan sayfanın  beirlenmesi   gerekmektedir.   Bu   amaçla   eğer   otopark   dolu   ise  hataSayfasi  niteliğinde   tutulan   adrese   (yeniden  yönlendirme   /   redirect   yapıldığı   için   bir   adres   verilmesi   gerekiyor)   yönlendirme   gerçekleştiriliyor.   Bu   niteliğin  tutulmasının   sebebi   gidilecek   sayfayı   kodun   içi   yerine,   yapılandırma   kütüğüne   yazmanın   tercih   edilmesidir.   Eğer  otopark dolu değilse hiç bir şey yapılmasına gerek yoktur ve true döndürülür, bu da aracGirisDenetimci'nin  çalıştırılmasına izin verir. Kod 2.30'da yapılandırma kütüğünde yapılan değişiklikleri görebilirsiniz. <property name="sessionForm">true <property name="commandName">aracGirisi

<property <property <property <property


name="commandClass">komut.AracGirisi name="validator"> name="formView">aracgiris name="successView">index.htm

<property name="mappings"> <props> <prop key="/index.htm">anasayfaDenetimci <prop key="/basit.htm">basitDenetimci <property name="hataSayfasi">index.htm <property name="interceptors"> <list> <property name="mappings"> <props> <prop key="/aracgiris.htm">aracGirisFormDenetimci <property name="viewClass"> org.springframework.web.servlet.view.JstlView <property name="prefix">/WEB-INF/jsp/ <property name="suffix">.jsp <property name="basename">mesajlar
Kod 2.30 springornek/WEB-INF/springornek-servlet.xml Artık  aracGirisFormDenetimci'ye   gelen   istekler  urlEsleme  adlı   işleyici   eşleme   nesnesi   tarafından   ele  alınmıyor, onun yerine  aracGirisUrlEsleme  adlı yeni eklediğimiz nesne kullanılıyor. Bu nesne işleyici eşleme  özelliğinin   yanı   sıra  aracGirisiDurdurucu'nun   da   dikkate   alınmasından   sorumlu   tutuluyor.   Dikkat   edilmesi  gereken   diğer   bir   husus   da  aracGirisiDurdurucu'nun  haftaSayisi  niteliğinin   değerinin   burada  anasayfa.htm olarak belirlenmesidir. Son değişikliklerin ardından uygulamayı çalıştırıp, otopark tamamen doluncaya kadar araç girişi yapar ve ardından ana  sayfadaki araç girişi bağlantısını tekrar tıklarsanız araç girişi sayfasına yönlendirilmediğinizi, hala ana sayfada kalmaya  devam ettiğinizi görebilirsiniz.

Sonuç Eğer   belgeyi   baştan   sona   dikkatlice,   örnekleri   çalıştırarak   ve   hatta   üzerinde   oynamalar   yaparak   okuduysanız   artık  Spring   MVC   çatısının   temel   kavram   ve   işlevleri   hakkında   önemli   derecede   fikir   sahibi   olduğunuzu   söyleyebiliriz.  Başlangıç düzeyinde hazırlanan bu belgede, Spring MVC ile acısız bir şekilde tanışılması hedefiyle, önemli kavramlara  ve öğrenme döneminde sorun çıkartabileceği düşünülen noktalara öncelik tanıyarak yer verilmeye çalışıldı.   Belgenin içerisinde de sık sık belirtildiği gibi burada bir çok konuda Spring MVC'nin sağladığı tüm seçeneklere yer  vermek yerine en sık kullanılanara değinilmeye ve örneklerde bunların kullanımına özen gösterildi. Böyle bir tercih  yapılmasının sebebi öğrenme döneminde kafa karışıklığının ortaya çıkmasından sakınmaktı. Ancak şu andan itibaren  sağlanılan tanışıklılık sayesinde başvuru belgesi (reference manual), javadoc belgeleri vb. geniş kapsamlı kaynaklardan  yararlanmakta zorluk çekilmeyeceği ön görülebilir. Bundan sonraki aşamada uygulamaya burada yer vermediğimiz araç çıkışı işlevini sağlayan bir sayfayı eklemek ve veri  üzerindeki işlemlerin bir veri tabanına taşımak faydalı denemeler olabilir.  Spring'in sağladığı esnek ve yapılandırılabilir yapı sayesinde Spring MVC'nin gücü Spring'in veri tabanı desteği veya  daha   farklı   bir   çok   konuda   sağladıkları   ile   birleştirilerek   çok   yetenekli   uygulamalar   ortaya   çıkartılabilir.   Spring'in  Hibernate benzeri veri tabanı teknolojilerini, çeşitli görünüm teknolojilerini ve hatta Struts'la birlikte çalışmayı ve daha  bir   çok   farklı   teknolojiyi   desteklediğini   de   göz   önüne   aldığımızda   ufkunun   ne   kadar   geniş   olduğu   ve   kullanım  yaygınlığının   daha   uzun   süre   artarak   devam   edeceği   ortaya   çıkıyor.   Bu   durumda   henüz   işin   başında   olduğumuzu  söylemek sanırım yanlış olmaz.  

Terimler Sözlüğü Attribute Bean Bind Command(Class) Container Constructor Controller Design Pattern Directory File Front Controller Handler  Handler Mapping Implement (an Interface) (Array) Index Interceptor Interface Map Mapping Method Override Package Redirect Request Response Tag Validation View View Resolver

Nitelik Çekirdek Bağlama Komut  Koza Yapılandırıcı Denetimci   Tasarım Örüntüsü Kılavuz (Kütük) Kütük Ön Denetimci  İşleyici İşeyici Eşleme  Uygulamak Dizin Durdurucu Arayüz Harita Eşleme Yöntem Yeniden yazmak Paket Yeniden Yönlendirme İstek Yanıt Etiket Doğrulama  Görünüm Görünüm Çözümleyici

Kaynaklar http://www.springframework.org/docs/reference/ http://www.ociweb.com/ http://www.theserverside.com/articles/article.tss?l=SpringFramework http://www.devx.com/Java/Article/22134/0/page/1 http://www.128.ibm.com/developerworks/web/library/wa­spring3/

Related Documents