SpringBoot – 3 (Thymeleaf)

Selamlar, bu yazımızda Thymeleaf ‘den bahsedeceğim. Spring ile entegresini yapıp bir kaç özelliğini kullanacağım. Thymeleaf, açık kaynak olarak geliştirilen, Servlet tabanlı çalışan bir template engine‘ dir. Daha önce eğer JSP kullanarak bir şeyler yaptıysanız Thymeleaf veya benzeri FreeMarker, Apache Velocity gibi diğer template engine‘lerin  avantajlarını daha iyi anlayabilirsiniz. Ön yüzde  size gerçekten esneklik sağlamakta.  Buradan daha detaylı bilgi alabilirsiniz. Şimdi SpringBoot ile entegresine geçelim. İlk önce bağımlılığımızı ekleyelim. (Bu yazımda da daha önceki projemden ilerliyorum.)

pom.xml

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Ardından resources klasörü içindeki templates klasörüne index.html dosyamızı ekleyelim.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Thymeleaf Examples</title>
</head>
<body>
Test
</body>
</html>

Sonrasında HomeController sınıfımızı aşağıdaki gibi düzenleyelim.

HomeController.java

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Created by ufuk on 8.8.2016.
 */
@Controller
public class HomeController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String displayHomePage(Model model) {

        return "index";
    }
}

Controller‘daki metodumuz da olusturduğumuz html dosyanın adını return ediyoruz. Ardından projeyi run edip http://localhost:8080/SpringGiris/ istek yaptığımızda index.html dosyamızın içeriği gelmektedir. Bu kadar kolay işte 🙂 Şimdi basit olarak for, if ve attribute yazdıralım ekrana.

Controller sınıfımızı düzenleyelim.

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Created by ufuk on 8.8.2016.
 */
@Controller
public class HomeController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String displayHomePage(Model model) {

        List<String> uuids = getUUIDList(10);

        model.addAttribute("list", uuids);
        model.addAttribute("isEmpty", uuids.isEmpty());
        model.addAttribute("fullName", "Ufuk Halis");

        return "index";
    }

    private List<String> getUUIDList(int limit) {
        List<String> uuids = new ArrayList<>();
        for (int i = 0; i < limit; i++) {
            uuids.add(UUID.randomUUID().toString());
        }
        return uuids;
    }
}

Rastgele değerler üretip bir liste oluşturdum. Daha sonra bu listeyi ve başka değerleri Metodumuzun model parametresine addAttribute şeklinde ekledik. Artık View kısmından bu değerlere ulaşabiliriz. index.html dosyamızı da düzenlersek.

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
    <title>Thymeleaf Examples</title>
</head>
<body>
<h1 th:text="'Full Name : ' + ${fullName}"></h1>

<h1>UUIDS</h1>
<p th:each="item : ${list}" th:text="${item}"></p>

<p th:if="${isEmpty}" >Empty</p>
<p th:if="${!isEmpty}" >Not Empty</p>

</body>
</html>

Evet, controller da set ettiğimiz attribute‘lere ulaşıp ekrana bastık, each ile listemiz içinde döndük, if ile de koşul durumunu gördük. Thymeleaf ‘in bu özelliklerini JSP kodlarken JSTL ile de yapabiliriz. Ancak tabi Thymeleaf ‘in ayıran özelliklerini fragment‘lar, SpringSecurity ile olan ilişkisi, hazır metotları vb. özelliklerini ilerleyen yazılarda zamanı geldikçe değineceğim. Şimdilik bu kadar. 🙂

Ya İyi Olarak Ölürsün, ya da kötüye dönüşecek kadar uzun yaşarsın
(The Dark Knight – 2008)

Advertisements

SprinBoot – 2 (Hibernate)

Merhaba, bu yazımızda SpringBoot veritabanı işlemleri ile devam edeceğiz. Önceki yazımdaki projeyi kullanacağım. SpringBoot ile veritabanı ayarları sizde görünce hak vereceksiniz oldukça kolay.

Yazımda Hibernate falan üzerinde çok durmayacağımdan o yüzden entity sınıflarındaki notasyonların hepsini açıklamayacağım. Belki hibernate için ayrı bir yazıda anlatabilirim. Bu yazımdaki amaç SpringBoot ile bu işlemleri yapmak.

Örneğimizde User ve Address adında iki entity sınıfımız olacak ve uygulama ayağı kalkma anında veritabanımıza kayıtlar ekleyip okuyup sonrasında sileceğiz.
Öncelikle pom.xml dosyamıza gerekli bağımlılıkları ekleyelim.

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <scope>runtime</scope>
</dependency>

Veritabanı olarak ben MySQL kullanıyorum. Siz herhangi bir veritabanı kullanabilirsiniz. Ona göre connector bağımlılığınızı eklemeniz gerekir.

Ardından application.properties dosyamızı gerekli eklemeleri yapalım.

spring.datasource.url = jdbc:mysql://localhost:3306/boot_hibernate_db
spring.datasource.username = root
spring.datasource.password = root
# Keep the connection alive if idle for a long time (needed in production)
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
# Show or not log for each sql query
spring.jpa.show-sql = false

# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = create-drop
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

Evet, veritabanı yolumuzu, kullanıcı adı ve parola bilgilerini, Spring jpa ile ilgili ayarlarımızı bu şekilde yapabiliyoruz. Ardından User ve Address entity ‘lerimiz ekleyelim. Entity notasyonu ile etiketlenen sınıflar Hibernate tarafından tablo olarak dönüştürülür. Sınıf elemanları da kolon olarak dönüştürülür.  Bizim User ile Address arasında OneToMany ilişkisi olacak, bir kullanıcının birden fazla adresi olabilir anlamına geliyor bu da.

User.java

import javax.persistence.*;
import java.io.Serializable;
import java.util.List;

/**
 * Created by ufuk on 10.8.2016.
 */
@Entity
public class User implements Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String firstName;
    private String middleName;
    private String lastName;

    @OneToMany(mappedBy = "user")
    private List<Address> addresses;

    public void setAddresses(List<Address> addresses) {
        this.addresses = addresses;
    }

    public List<Address> getAddresses() {
        return addresses;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getMiddleName() {
        return middleName;
    }

    public void setMiddleName(String middleName) {
        this.middleName = middleName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

Address.java

import javax.persistence.*;
import java.io.Serializable;

/**
 * Created by ufuk on 10.8.2016.
 */
@Entity
public class Address implements Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String address;
    @ManyToOne
    @JoinColumn(name = "user")
    private User user;

    public void setId(long id) {
        this.id = id;
    }

    public long getId() {
        return id;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getAddress() {
        return address;
    }
}


Projeyi bu haliyle çalıştırdığımızda gerekli tablolar belirttiğimiz veritabanında oluşacaktır. Şimdi ise Repository interface‘lerimizi oluşturalım. Repository interface‘lerimiz sayesinde CRUD işlemlerini gerçekleştireceğiz.

UserRepository.java

import com.ufuk.entity.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by ufuk on 10.8.2016.
 */
@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Long> {
}

AddressRepository.java

import com.ufuk.entity.Address;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by ufuk on 10.8.2016.
 */
@Repository
@Transactional
public interface AddressRepository extends CrudRepository<Address, Long> {
}

Evet görüldüğü gibi Repository notasyonu ile etiketleyip CrudRepository sınıfından extend ediyoruz.

Ardından Main sınıfımızı düzenleyelim.

SpringBootGirisApplication.java
import com.ufuk.entity.Address;
import com.ufuk.entity.User;
import com.ufuk.repository.AddressRepository;
import com.ufuk.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.Arrays;

@SpringBootApplication
public class SpringBootGirisApplication implements CommandLineRunner{

   @Autowired
   UserRepository userRepository;

   @Autowired
   AddressRepository addressRepository;

   public static void main(String[] args) {
      SpringApplication.run(SpringBootGirisApplication.class, args);
   }


   @Override
   public void run(String... strings) throws Exception {
      Address address = new Address();
      address.setAddress("Arlington Street, 1578");

      User user = new User();
      user.setFirstName("Ufuk");
      user.setLastName("Halis");
      user.setAddresses(Arrays.asList(addressRepository.save(address)));
      user = userRepository.save(user);

      readData();

      userRepository.delete(user);

      readData();

   }

   private void readData() {
      Iterable<User> userIterable = userRepository.findAll();
      if (!userIterable.iterator().hasNext()) {
         System.out.println("No data found!");
      }
      for (User u : userIterable) {
         System.out.println("First Name : " + u.getFirstName());
         System.out.println("Last Name : " + u.getLastName());
         for (Address a : u.getAddresses()) {
            System.out.println("Address : " + a.getAddress());
         }
         System.out.println("*******************************");
      }
   }
}

Evet, görüldüğü gibi basit olarak bir kullanıcı ve adres ekledik, okuduk ve sildik ve bunu yarattığımız Repository sınıflarıyla yapabildik. Repository sınıflarımıza kendi metot gövdelerimizi ekleyebiliriz. Örneğin bir kullanıcıyı firstName alanına göre bulmak istersek şu şekilde bir metot gövdesi eklememiz yeterli.

User findByFirstName(String firstName);

Spring Data metot isminden gerekli sorguyu yapacak ve sonucu döndürecektir. Custom query oluşturmak için de metodumuzu Query notasyonu ile etiketlemek yeterli. Ardından içine query‘imizi yazabiliriz.

Uygulamayı çalıştırdığımızda aşağıdaki ekran görüntüsü gibi bir çıktı alacağız.Ekran Alıntısı.PNG

Evet, bu yazımızda bu kadar. Basit olarak SpringBoot ile bir veritabanına bağlandık, kayıt sildik ekledik vs.  Sonraki yazılarda görüşmek üzere…

Bu ve bundan sonraki yazıları filmlerden alıntılar ile bitireceğim artık, kullandığım bitiriş cümlesi çok beğenilmedi arkadaşlar tarafından 🙂

-Kaşığı eğmeyi boşa deneme. Bu imkansızdır. Bunun yerine sadece gerçeği anlamaya çalış.Tamam mı?
-Gerçek nedir?
-Aslında bir kaşık yok. Eğilen sadece kendinsin.
(Matrix)

SpringBoot – Giriş

Merhabalar, uzun bir aradan sonra son zamanlarda çok içli dışlı olduğum bir framework’ten bahsedeceğim. SpringBoot. Evet Spring framework’u biliyoruz. Kendisi Java dünyasında defacto standartı olarak kabul edilir. Dependency Injection ve IOC bu framework’un temel taşlarıdır. Spring framework’te konfigürasyon işlemleri ilk başlarda XML üzerinden hep yürürdü. Tabi zamanla annotation bazlı konfigürasyonlarda popüler oldu. Ancak bazı durumlarda Spring agile olamama durumu, yaygınlaşan microservices olayları SpringBoot’un doğmasına neden oldu. Evet SpringBoot ile çok hızlı, fazla konfigürasyon işlerine girmeden projeler oluşturabilir. Jar ve War çıktıları alabilirsiniz. Bu yazımda Intellij Idea üzerinde bir SpringBoot projesi oluşturup ayağı kaldıracağız.

Evet Ide’mizi açtıktan sonra New Project deyip Sol taraftan Spring Initialzr’ı seçip ilerliyoruz.

new_project

Ardından gelen ekran projemizle ilgili konfigürasyonları yapıyoruz. Type olarak Maven veya Gradle, dil olarak Groovy, Java ve Kotlin, çıktı olarak Jar veya War seçebilirsiniz.

new_project2.png

Daha sonraki gelen ekranda ihtiyacımız olan bağımlılıkları projemize seçip ekleyebiliriz. Bizim uygulamamız basit bir uygulama olacağı için sadece Web bağımlılığını ekliyorum.

new_project3.png

Devam edip Finish dediğimizde aşağıdaki resimdeki gibi bir proje yapısı ve bir adet main sınıfımız geliyor.

project_folder.png

src klasörü altında java class‘larının yer aldığı java klasörü ve resources klasörü bulunmakta. pom.xml ‘den anlayabileceğimiz gibi bizim projemiz Maven tipinde. resources içinde application.properties(Konfigürasyonların yapıldığı dosya kendisi.), static(js,images,css vb.) ve templates(html dosyalarımızı koyacağımız yer). SpringBoot Thymeleaf ile oldukça uyumlu bende projelerde Thymeleaf tercih ediyorum. Siz başka bir template engine kullanacağınız gibi sadece jsp de kullanabilirsiniz.

Bu şekilde projemizi run ettiğimizde ayağı kalkacaktır. Ancak herhangi bir controller vs oluşturmadığımız için not found tarzında bir hata alırız. Öncelikle application.properties dosyamıza aşağıdaki kodları ekleyelim.

server.contextPath=/SpringGiris
server.port=8080

Gördüğünüz gibi port numarası ve context path atamasını böyle yapabilirsiniz. Sonra HomeController adında bir sınıf ekleyelim. İçeriğide aşağıdaki gibi olsun.

package com.ufuk;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Created by ufuk on 8.8.2016.
 */
@Controller
public class HomeController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ResponseEntity<String> displayHomePage(Model model) {

        return new ResponseEntity<>("SpringBoot Merhaba", HttpStatus.OK);
    }
}

Evet daha önceden Spring ‘ de bir controller yazdıysanız hiçbir farkı yok. http://localhost:8080/SpringGiris/ adresine isteğimizi atınca sonuç olarak aşağıdaki ekranı alıyoruz.

son.png

Evet şimdilik bu kadar. Sonraki SpringBoot yazılarında Veritabanı bağlantıları, Spring Data, SpringSecurity vs kullanarak aynı projeyi genişleteceğim. Görüşmek üzere…

Test edilmeyen kod tuhaflaşır…