Spring Boot ile Örnek Web Uygulaması

Kod Gemisi Blog
Jun 1, 2017 · 18 min read

(Bu yazı Kod Gemisi Blog arşivinden alınmış olup, 25 Ağustos 2015 tarihinde Sedat Gökcen tarafından yazılmıştır.)

Bu yazıda size Spring Boot ile ilgili kısa bir bilgi verip, geliştirdiğim demirbaş takip uygulamasını aşama aşama anlatmaya çalışacağım.

Spring Boot Nedir?

Spring Boot, Spring tabanlı uygulama geliştirmenin en hızlı ve kolay yolu olması amacıyla geliştirilmiş bir frameworktür. Spring Boot sayesinde boilerplate yani basmakalıp kodlardan sıyrılıp, sadece ihtiyacımız olan kodu yazıyoruz (only write code that you need to). Spring Boot web sunucusu olarak Tomcat ve diğer birçok ek özellikle beraber geliyor.

Spring Boot’un sağladığı en büyük avantajlardan biri ise sizi herhangi bir XML konfigürasyonuyla uğraşmak zorunda bırakmaması.

Uygulama Gereksinimleri ve POM Dosyası

Spring Boot ile yazacağımız uygulamamız, şu gibi gereksinimleri karşılayacak:

  1. Kullanıcı adı unique olmak şartıyla, kayıtları databasede tutulan basit bir üyelik sistemi,
  2. Sadece sisteme giriş yapmış üyelerin görebileceği birer item ve kullanıcı listesi
  3. Yine sadece üyelerin müdahale edebileceği, database’e yeni item ekleme, item çıkarma ve itemın sorumluluğunu herhangi bir kullanıcıya atama

Yukarıdaki 3 gereksinimde de karşımıza çıkmasına rağmen ben güvenlik ve yetkilendirme aşamalarını (üye kaydı-girişi vs.) en sona bırakıp, öncelikle item ekleme, item çıkarma ve itemı herhangi bir kullanıcıya atama işlemlerini anlatmaya çalışacağım. Uygulamanın kaynak kodlarına buradan ulaşabilirsiniz.

İşe, ihtiyaç duyacağımız kütüphaneleri kullanabilmek için gerekli dependencyleri pom.xml dosyasına eklemekle başlayalım:

spring-boot-starter-data-jpa ve h2 uygulamamızdaki database gereksinimi için, thymeleaf ise view katmanında template engine olarak kullanacağımız Thymeleaf için gerekli dependencyler. Daha sonra pom.xml dosyamıza iki dependency daha ekleyeceğiz.

Spring Boot ile İlk Web Sayfası

Her şeyden önce dosya yapımızı aşağıdaki gibi ayarlayalım:

Dilerseniz dosya yapımızı oluşturduktan sonra Model katmanındaki classları oluşturmaya geçmeden ana sayfamızı oluşturalım. Bunun için ihtiyacımız olanlar resources/templates altında home.html sayfası ile controller altında HomeController ve ana dizinde Application classları.

HomeController şu aşamada gayet basit, sadece home viewunu döndürüyor, bunu daha sonra değiştirip, o anda giriş yapmış olan User‘ı da döndürmesini sağlayacağız.
RequestMapping(“/”) ile http://localhost:8080/ adresine bir GET isteği yaparak, hazırlayacağımız home.html sayfasına bu adresten erişilmesini sağlıyoruz.
Peki, ana sayfaya http://localhost:8080/home adresinden de erişmek istiyorsak ne yapacağız? Çözüm çok basit. RequestMapping, parametre olarak bir String arrayi alabiliyor. Yani yapacağımız işlem şu:

Şimdi de home viewumuza bir göz atalım:

Şu an home.html sayfamız standart bir HTML sayfası, sizin de 2. satırdan anlayacağınız üzere bu sayfada Thymeleaf kullanacağız. Bunu sonraya bırakıyor ve Spring Boot ile hazırladığımız web uygulamasını ayağa kaldırmak için ihtiyacımız olan son classımızı yazıyoruz:

Application, uygulamamızın üzerinde çalışacağı main methodunu barındıran bir class olacak.

İşlem tamam! Şimdi uygulamamızı IDE üzerinden çalıştırıp, http://localhost:8080/ adresine gittiğimizde bizi Welcome! yazısı bekliyor olmalı. Bunun yerine herhangi bir hatayla karşılaşıyorsanız lütfen önceki adımları tekrar dikkatle inceleyin, pom.xml‘deki dependencylerin ve dosya yapınızın yukarıdakiyle aynı olduğundan emin olun.

! Uyarı !

Tabii ki dosya yapınız benimkiyle birebir aynı olmak zorunda değil, package isimleriniz ve class isimleriniz farklılık gösterebilir. Burada değineceğim asıl nokta şu: dosya yapınızın beklenenden çok farklı olması bazı durumlarda uygulamanızın çalışmasını etkileyebilir. Örnek vermek gerekirse, Application classının doğrudan src/java altında olması “Your ApplicationContext is unlikely to start due to a @ComponentScan of the default package” gibi bir hata almanıza ve uygulamanızın çalışmamasına sebep olacak.

Spring Boot ile ilk web sayfamızı hazırladık. Sıra geldi uygulamamızın gereksinimlerine.

Item Ekleme

Senaryomuzu hazırlamak için gerekli yapıları katman katman hazırlayalım.

Item ekleme senaryosu için ihtiyacımız olan ilk model sizin de tahmin edeceğiniz üzere Item. domain package’ı altında Item classımızı oluşturalım.

Gördüğünüz gibi Item modelimiz aynı zamanda oluşturacağımız database için bir Entity olacak. @GeneratedValue anotasyonuyla primary key olan id‘yi otomatik olarak oluşturuyoruz. inventoryCode, her item için farklı olacak bir stok kodu, bu kodu item’ı database’e ekleme aşamasında random bir string üreterek oluşturacağız. type‘ı ise bilgisayar, telefon, yatak vs. gibi itemın cinsi olarak düşünebilirsiniz.

Ben yazıdaki kod kısmını mümkün olduğunca kısa tutmak istememden dolayı set ve get methodlarını yukarıya eklemedim, siz kendi projenizde eklemeyi unutmayın.

Oluşturmamız gereken bir adet modelimiz daha var: ItemAddForm

Bu modeli, View katmanında hazırlayacağımız item ekleme formunun modeli olarak düşünebilirsiniz. ItemAddForm‘un görevi ihtiyacımız olan datayı View katmanından alıp Service katmanına taşımak. Bu taşıma işini yapan objelere DTO (Data Transfer Object) deniyor. DTO ile Model katmanında kullandığımız ana objelerin arasındaki fark, DTO’ların datayı alma ve datayı kaydetme harici (set ve get methodları) herhangi bir sorumluluğu olmaması, yani üzerlerinde başka method tanımlanmamasıdır.

Şimdi yine domain altında ItemAddForm classını oluşturalım.

@NotEmpty, @NotNull ve @Size Hibernate Validator anotasyonları. Bunları kullanarak kullanıcıdan aldığımız bilginin Service’e taşınmadan istediğimiz şekilde olduğuna emin olmuş oluyoruz. String tipindeki itemType için @NotNull değil, @NotEmpty anotasyonunu kullandığımıza dikkat edin.

Service katmanının ne olduğunu, ne iş yaptığını açıklamadan önce, Service implementasyonlarında bolca kullanacağımız repository kavramını bir cümleyle tanımlayacak olursak: Repository, database’de tuttuğumuz dataya erişim objemiz, yani bilinen adıyla DAO (Data Access Object).

Biz kendi senaryomuz için ItemRepository adında bir interface oluşturup, bu interfacede CrudRepository‘i extend ederek save, delete, find gibi methodları Item entitymiz üzerinde kullanılabilecek duruma geleceğiz.

repository package’ı altında ItemRepository adında bir interface oluşturalım.

Item, üzerinde işlem yapacağımız entity, Long tahmin edeceğiniz üzere bu entity’nin idsinin type’ı.

Şu anlık ItemRepository‘e kendimiz herhangi bir method tanımı eklemeyeceğiz, yukarıda da bahsettiğim üzere CrudRepository‘den gelen save, delete, find vs. gibi methodlar bizim için yeterli. Repositorymizi oluşturduğumuza göre Service katmanına geçelim.

Service, aslında Controller’da olabilecek business logic’i encapsulate etmek için yarattığımız, Controller ve Model arasında duran bir katmandır. Service katmanının sorumluluklarını model objesini almak, yaratmak, güncellemek olarak sıralayabiliriz.

service package’ı altında ItemService adında bir interface ve ItemServiceImpl adında bir class oluşturalım.

ItemAddForm‘dan bize itemın type’ı (bilgisayar, telefon vs.) ve bu itemdan stoka kaç tane ekleneceği bilgisi geliyor. Bu bilgilere göre Item objesini yaratıp, save methoduyla database’e ekliyoruz.

inventoryCode‘u nasıl oluşturduğumuza takılmayın, o satırda yaptığımız tek işlem 6 karakter uzunluğunda alfanümerik bir string oluşturmak.

controller package’ı altında ItemController classını oluşturalım.

itemAddPage methodunda http://localhost:8080/items/add adresine GET isteği yapıp item ekleme sayfasına ulaşıyoruz. Burada HomeController‘daki gibi sadece String döndürmememizin sebebi, View’un yanında bir de ItemAddForm modeline ihtiyacımız olmamız. Yarattığımız ModelAndView objesinin constructorında “addItem” viewun adını, “itemForm” bu viewda kullanacağımız modelin adını, yarattığımız ItemAddForm objesi ise anlayacağınız üzere bu viewda kullanacağımız modeli belirtiyor. Bu kısımda biraz kafanız karışmış olabilir ama viewumuzu yani addItem.html‘i oluşturduğumuzda her şeyi daha net anlayacağınızı düşünüyorum.

itemAddPage methodunda hazırlayacağımız view’u gösterme işini hallettik, handleItemAdd methodunda ise adından da anlaşılacağı üzere item ekleme işini hallediyoruz. Bu methoddaki @Valid anotasyonunu ve bindingResult parametresini form validationı için kullanıyoruz. Validation kısmında herhangi bir sorun olmadığı takdirde ItemService‘in içinde oluşturduğumuz addItem methodu ile itemımızı database’e ekliyoruz.

Item ekleme senaryosunu tamamlamak için ihtiyacımız olan son katmanı hazırlayalım şimdi de. resources/templates altında addItem.html sayfasını oluşturalım.

Yukarıda standard HTML harici gördüğünüz, th ile başlayan her blok Thymeleaf’e ait. Sırayla açıklamak gerekirse eğer:

  • th:action‘daki URL’in, Controllerda POST isteğini yaptığımız handleItemAdd methodunda kullandığımız RequestMapping‘in değeriyle aynı olduğuna dikkat edin. @ sembolü bir URL expression, Thymeleaf kulladındığımız HTML sayfalarında link paylaşmak istediğimizde bu sembolü kullanıyoruz.
  • th:object alanında variable expression’ı olan $ sembolünü kullanarak, Controller’da @ModelAttribute anotasyonuyla belirttiğimiz ItemAddForm objesini kullanacağımızı belirtiyoruz.
  • th:field alanında ise kullanıcıdan gelen inputu, th:object‘te belirttiğimiz objenin hangi attributeuna set edeceğimizi yazıyoruz. Burada kullandığımız sembolün * olduğuna dikkat edin.
  • th:if ile başlayan blok oldukça açık. Form validationında herhangi bir sıkıntı olması durumunda hatayı yazdırıyoruz.

Kullandığımız Thymeleaf expressionlarıyla ilgili daha fazla bilgiye buradan, Spring için Thymeleaf dökümantasyonuna ise buradan ulaşabilirsiniz. Dökümantasyonların gayet açıklayıcı olduğunu söyleyebilirim.

Sonunda ilk gereksinimimizi tamamladık, şimdi test edelim. ItemServiceImpl classındaki addItem methodunda, for döngüsünün son satırına aşağıdaki satırı ekleyelim:

findOne methodu, parametre olarak verdiğimiz id‘ye sahip Item‘ı databaseden bulup döndürecek. Item classımıza toString methodunu ekleyelim, daha doğrusu bu methodu override edelim.

Şimdi uygulamamızı IDE üzerinden çalıştırıp, http://localhost:8080/items/add adresine gidip, istediğimiz miktarda ve typeta item ekleyelim. POST isteğini http:localhost:8080/items sayfasına yaptığımızdan bu sayfaya yönlendiriliyoruz. Bu sayfayı henüz hazırlamadığımız için Request method ‘GET’ not supported gibi bir hata alacaksınız, önemsemeyin, bu sayfayı sonraki aşamada hazırlayacağız. IDE’nize geri döndüğünüzde, konsolda eklediğiniz itemları göreceksiniz:

Şimdi sıra geldi eklediğimiz itemları http:localhost:8080/items adresinde listelemeye.

Itemları Listeleme ve Silme

Bu kısım çok daha kısa sürecek, hemen başlayalım.

ItemService interfaceimize aşağıdaki 2 method tanımını ekleyelim:

Şimdi ise, ItemServiceImpl classında bu methodların implementationlarını yapalım:

Gördüğünüz gibi aslında bizim yaptığımız pek bir şey yok. CrudRepository‘den gelen methodları Service içinde kullanıyoruz. Bunu yapmamızın sebebi Controller’da hem Service hem Repository kullanmak yerine, sadece Service’i kullanmak istememiz.

ItemController‘a aşağıdaki iki methodu ekleyelim.

getItemsPage methodunda, items.html sayfasına, ismi items olan modelimizi gönderiyoruz. Bu kez modelimiz databasedeki tüm itemlar, bu itemlara ItemService içerisindeki, az önce yazdığımız getItems methoduyla erişiyoruz.

handleItemDelete methodunda ise itemı silme işlemini kontrol ediyoruz. http://localhost:8080/items/{id} adresine(örneğin, http://localhost:8080/items/1) DELETE isteği yapıp, adreste belirttiğimiz id değişkenindeki değere sahip itemı siliyoruz. URL’de kullandığımız bu değişkenlere PathVariable diyoruz. Silme işlemi tamamlandıktan sonra kullanıcıyı tekrar http://localhost:8080/items adresine yönlendiriyoruz.

resources/templates altında items.html sayfasını oluşturalım.

Thymeleaf’te th:each ile java.util.List objelerini, java.util.Iterable‘ı implement eden objeleri, java.util.Map‘i implement eden objeleri ve arrayleri iterate edebilirsiniz. Databasedeki her item için delete butonu ile itemın stok kodunu ve typeını yazdırıyoruz. Delete işlemi için Controller’da belirttiğimiz gibi http://localhost:8080/items/{id} adresine DELETE isteği yapıyoruz.

Itemin sorumluluğunu herhangi bir usera atama hariç, itemlarla ilgili gereksinimlerimizi tamamladık. Sıra geldi userlar ile ilgili gereksinimlere.

User Kaydı ve Userları Listeleme

Her zaman olduğu gibi Model katmanıyla başlıyoruz.

domain package’ı altında User classımızı oluşturalım.

Burada açıklama yapmayı gerek duyduğum tek kısım @OneToMany anotasyonu kulladığımız items Seti. Tahmin edeceğiniz üzere, User ve Item aralarında one-to-many ilişkisi olan birer Entity. User‘ın itemlarını bu Set içerisinde belirtiyoruz. Şimdi de Item tarafına, itemın sahibi User‘ı ekleyelim:

@OneToMany anotasyonu hakkında daha fazla bilgiye buradan ulaşabilirsiniz, ben fazla üzerinde durmayacağım.

Modelimiz hazır olduğuna göre her zaman olduğu gibi sırada Service katmanı var.

Öncelikle, repository altında UserRepository interfaceimizi oluşturalım.

Aynı ItemRepository’de yaptığımız gibi burayı şimdilik boş bırakalım ve service package’ı altında UserService’i oluşturalım:

UserServiceImpl ise:

Controllerımız da yine ItemController ile çok benzer. Dikkat ederseniz bu sefer UserAddForm gibi bir DTO oluşturup, viewa o DTO’yu göndermek yerine doğrudan bir User objesi gönderdik. Yazının iyice uzamasını istemediğimden ve eğer oluştursaydım, UserAddForm, User objesi ile birebir aynı attributelara sahip olacağından bu kez DTO oluşturma işini pas geçtim. Siz dilerseniz bu kısımda da bir DTO oluşturabilirsiniz.

resources/templates altında register.html ve users.html sayfalarını yaratalım.

Bunlar da Item için hazırladığımız sayfalarla çok benzer, açıklayacak yeni bir şey olduğunu düşünmüyorum. http://localhost:8080/register adresinde user kaydı yapıp, bu userların listesine http://localhost:8080/users adresinden ulaşabilirsiniz.

User kaydı ve listeleme işlemi tamam, ama unutmayın şu an yaptığımız tek şey kayıt formu doldurulduğunda, User‘ı database’e kaydetmek. Sayfaları kayıtlı olmayan userlara kapatma, kullanıcı girişi gibi güvenlik işlemlerini en sona bırakıp, bir sonraki gereksinimimize geçiyorum.

Itemları Kullanıcıya Atama

Itemları ve userları başarıyla ekledik, peki ama hangi item hangi usera ait? x kişisinin sorumlu olduğu itemlar neler? Bu soruların cevaplarını verebilmek için yeni senaryomuza geçelim.

Model katmanına geçmeden, bu senaryoyu tamamladığımızda nasıl bir görüntü oluşturmak istediğimize bakalım:

Gördüğünüz üzere items sayfamızda bir takım değişiklikler yapacağız. Ama sırayı bozmayalım ve yine Model katmanıyla başlayalım.

Bu kısımda ItemAssignForm adında bir DTO yaratacağız.

Gördüğünüz gibi sadece tek attributeumuz var, bunun sebebini daha sonra anlayacaksınız. Ben her zamanki gibi set ve get methodlarını buraya eklemedim.

Yukarıdaki ekran görüntüsünde gördüğünüz üzere, bir select box içerisinde bütün kullanıcı adlarını listeliyoruz. Bunun için getUsernames gibi bir methoda ihtiyacımız var.

UserService’e aşağıdaki method tanımını ekleyelim:

Şimdi, UserServiceImpl‘da ise bunun implementasyonunu yapalım:

Artık kullanıcı adlarının listesi elimizde. Hatırlayacağınız üzere, User’ın bir item listesi, Item‘ın ise bir userı vardı. Yani kullanıcı Assign butonuna tıkladığında olmasını beklediğimiz şeyler, userın item listesine ilgili itemın eklenmesi ve bunun yanında, o itemın userı olarakta select boxdan seçtiğimiz userın set edilmesi. Bunun için ItemService‘e aşağıdaki method tanımlarını ekliyoruz:

Bunların implementationları ise:

Burada henüz yazmadığımız, UserService‘e ait bir getUserByUsername methodu var, bu methodu az sonra yazacağız. assignItem methodunu kısaca açıklayacak olursak, ItemAssignForm‘dan gelecek olan kullanıcı adına sahip userın item listesine, itemId‘ye sahip Item‘ı ekliyoruz. Daha sonra ise, bu itemın userını, getUserByUsername methoduyla aldığımız user’a set ediyoruz. En son yaptığımız işlem ise item’ın yeni halini database’e eklemek (Esasında buna bir update işlemi demek daha doğru olur).

getUserByUsername methodunu implement etmeden önce, UserRepository‘e aşağıdaki method tanımını ekliyoruz:

Normal bir Java uygulamasında, yukarıdaki methodun implementasyonunu yapmamız gerekirdi. Spring Data JPA sayesinde bunu yapmamıza gerek kalmıyor, o bizim için bu implementasyonu, method ismine göre kendisi yaratıyor. Özetle, bizim sadece tanımını yaptığımız findByUsername methodu, parametre olarak verdiğimiz username‘e sahip userı bulacak database sorgusunu yazıp, userı bize getiriyor. Şimdi yukarıda kullandığımız getUserByUsername methodunu yazalım.

UserService:

UserServiceImpl:

Service kısmında işimiz bitti, şimdi Controller’a geçelim.

Yukarıda http://localhost:8080/items sayfasını değiştireceğimizi söylemiştim. Şu anki haliyle, Controllerdan bu sayfaya sadece itemları gönderiyoruz. Ama yeni halinde, iki modele daha ihtiyacımız olacak. Birisi DTO’muz olan ItemAssignForm, diğeri ise select boxda göstermeyi hedeflediğimiz kullanıcı adları.

Peki, bir sayfaya birden fazla model nasıl göndereceğiz?

ItemController‘daki getItemsPage methodumuzun yeni hali böyle. Gördüğünüz gibi, birden fazla model göndermek için bir <String, Object> mapi oluşturup, modellerimizi bu mape ekledik.

ItemController‘daki yeni methodumuz ise:

Bu aşamada aslında bir update işlemi yaptığımız için, PUT isteği yolluyoruz. assignItem methodunun parametreleri DTO’dan gelen usernamei ve PathVariable olan item id‘sini kullanıyoruz. İşlem tamamlandıktan sonra kullanıcıyı items sayfasına yönlendiriyoruz.

Sıra geldi items.html sayfasındaki değişiklikleri yapmaya.

<table>’ın içeriğini yukarıdaki gibi değiştirdikten sonra bu gereksinimimizi de tamamlamış oluyoruz. Burada da açıklayacak pek bir şey yok, daha önce hazırladığımız formlardan tek farkı bir select box içermesi.

Artık eklediğimiz itemları, userlara atayabiliyoruz. Sıra geldi atadığımız bu itemları, kullanıcıların sayfasında göstermeye.

User Sayfası Oluşturup, Itemlarını Listeleme

Buradaki amacımız, her user için ayrı sayfa oluşturup, userların sorumlu olduğu itemları kategorilerine göre listelemek.

Bu kısımda Model katmanıyla bir işimiz yok, doğrudan Service katmanıyla başlıyoruz.

UserService interfaceine aşağıdaki method tanımlarını ekleyelim:

Bu methodların implementasyonları ise şöyle:

numberOfItemsByType methodunda <String, List<Item>> mapi oluşturuyoruz. Bu mapte keyimiz itemın typeı, valuemuz ise o typetaki itemların bir listesi. Bu senaryomuzdaki tüm işi neredeyse bu method yapıyor.

Controllerda öncelikle URL’deki id‘ye sahip bir user olup olmadığını kontrol ediyoruz. Eğer böyle bir user yoksa exception throw ediyoruz, eğer varsa da yukarda yazdığımız methodun döndürdüğü mapi viewumuza gönderiyoruz.

resources/templates altında userItems.html sayfasını oluşturalım:

Bu sayfada ilk defa karşılaştığımız şey, th:with ifadesi. th:with ile yukarıda döndürdüğümüz map’in valuesu olan item listesini itemList isimli bir değişkene atıyoruz. Aşağıda ise, bu itemList’teki her itemin inventoryCode’unu ve type’ını tek tek yazdırıyoruz.

Bu kısmıda tamamladık, artık her user için özel bir sayfamız var ve bu sayfada kullanıcıların sorumluluğundaki itemları listeleyebiliyoruz.

Artık uygulamamızı tamamlamak için son bir adım kaldı.

User Girişi

Öncelikle, pom dosyamıza aşağıdaki dependencyleri ekleyelim:

İlk dependencye, uygulamamızı güvenli hale getirmek ve yetkisiz kullanıcılara sayfaya giriş izni vermemek için ihtiyacımız var. İkinci dependency ise bize Thymeleaf’in bazı ekstra özelliklerini kullanabilmemizi sağlayacak.

UserDetails‘in görevi, aşağıdaki methodlardan da anlayacağınız üzere core user bilgisini bulundurmaktır. User modelimizde UserDetails interfaceini implement edelim ve şu methodları ekleyelim:

Aslında, UserDetails interfaceinde getUsername ve getPassword methodları da var ama biz zaten bu methodları modelimizi ilk oluşturduğumuzda yazmıştık.

getAuthorities methodunda sistemdeki yetkilerin bir listesini oluşturup döndürüyoruz. Bizim uygulamamızda bütün kullanıcıların yapabildiği işlemler aynı, bu yüzden USER adında sadece bir yetki ekliyoruz listeye. Örneğin, bu listeye ADMIN adında bir yetki ekleyebilir ve bu yetkiye sahip kullanıcıların, istedikleri kullanıcıyı sistemden silmesine olanak verebilirdik ama bu uygulama için böyle bir gereksinimimiz yok.

Username’in sistemimizde unique olacağını belirtmiştik. Dilerseniz, register sayfasına bir validator ekleyelim ve girilen kullanıcı adının sistemde zaten var olup olmadığını kullanıcıya bildirelim.

domain package’ı altında validator package’ı oluşturup, RegisterValidator classını yaratıyoruz:

Gördüğünüz gibi, bizim burada kontrol ettiğimiz tek şey girilen kullanıcı adının sistemde olup olmadığı. Eğer biz register sayfamızda onay için şifrenin iki kez girilmesini istesek, burada girilen iki şifrenin birbiriyle aynı olup olmadığını kontrol edebilirdik.

Model kısmıyla işimiz bitti, Service kısmına geçelim.

UserServiceImpl classımızda UserDetailsService interfaceini implement ediyoruz ve aşağıdaki methodu ekliyoruz:

UserDetailsService, Spring Security’nin user girişini (user, gerçekten var olan login formunu mu kullanıyor, girilen password doğru mu, user’ın sistemdeki rolü veya yetkileri nedir gibi) loadUserByUsername methoduyla kontrol ettiği bir interface.

Öncelikle LoginController classını oluşturalım:

@PreAuthorize anotasyonuyla, getLoginPage methodunun sadece giriş yapmamış kullanıcılar için invoke edileceğini belirttik. Eğer burada, @RequestParam olarak doğrudan String kullansaydık, ‘error is not present’ hatası alacaktık.

Şimdi ise yukarıda yazdığımız RegisterValidator classını UserController‘da kullanalım.

Gördüğünüz gibi, az önce yazdığımız validator classını initBinder içerisinde validator olarak ekledik.

config package’ı altında SecurityConfig classımızı oluşturalım:

configure methodu URL bazlı güvenliğin ayarlandığı kısım. Burada register ve home sayfaları hariç bütün sayfaları, giriş yapmamış kullanıcılara kapatıyoruz. login ve logout adreslerini de yine bu methodda belirtiyoruz.

View kısmına geçelim ve uygulamamızı tamamlayalım.

Yine resources/templates altında login.html sayfasını oluşturalım:

Burada değineceğim iki nokta var. sec:authorize=”isAuthenticated()” diyerek sadece giriş yapmış kullanıcılara özel içerik sunabiliyoruz. Bunu, yukarıda eklendiğimiz thymeleaf-extras-springsecurity3 dependencysi sayesinde kullanabiliyoruz. Artık, ana sayfamızı şu şekilde değiştirebiliriz:

Gördüğünüz gibi, isAuthenticated ve isAnonymous sayesinde giriş yapmış kullanıcılara ve giriş yapmayan ziyaretçilere farklı içerik sunabiliyoruz. Tabii, Welcome, {username}! yazdırmak şu aşamada mümkün değil. HomeController’ı aşağıdaki şekilde değiştirelim:

@AuthenticationPrincipal ile user‘ın o an sisteme giriş yapmış kullanıcı olduğunu belirtiyor ve bu user‘ı ana sayfada kullanacağımız model olarak döndürüyoruz.

Kod Gemisi

Kod Gemisi

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store