İşte 100 adımda Spring Boot öğrenmek ve uygulama geliştirmek için temel adımları içeren bir rehber:
1. Spring Boot Nedir?
- Spring Boot, Spring çerçevesinin hızlı ve kolay kullanımı için geliştirilmiş bir yapılandırma aracıdır. Minimal konfigürasyonla mikroservisler oluşturmanıza olanak tanır.
- Spring Boot, Spring Framework'ün hızlandırılmış ve basitleştirilmiş bir versiyonudur. Geliştiricilere minimal konfigürasyon gereksinimiyle, hızlı bir şekilde bağımsız, üretim seviyesinde Spring tabanlı uygulamalar geliştirme olanağı sağlar. Geleneksel Spring uygulamalarında birçok XML tabanlı yapılandırma gerekiyorken, Spring Boot, varsayılan ayarları kullanarak bu karmaşıklığı azaltır.
Spring Boot’un Sağladığı Avantajlar:
- Kolay Konfigürasyon: Varsayılan ayarlar ve otomatik yapılandırmalar sayesinde minimum manuel konfigürasyon.
- Yerleşik Sunucu: Tomcat, Jetty veya Undertow gibi yerleşik sunucularla uygulamanızı dış bir sunucuya deploy etmeden çalıştırabilirsiniz.
- Hızlı Başlangıç: Spring Initializr gibi araçlar sayesinde hızlıca proje oluşturabilir ve çalıştırabilirsiniz.
- Mikroservis Mimarisine Uyum: Mikroservis mimarisi için idealdir, dağıtık sistemler kurmaya uygundur.
- Üretim Seviyesi Hazırlık: Actuator, güvenlik ve kolay konfigürasyon seçenekleriyle üretim ortamı için güçlü bir altyapı sağlar.
Spring Boot, kompleks Spring uygulamalarının temellerini basitleştirerek hız ve verimlilik sağlar, bu da mikroservis ve bulut tabanlı çözümler için oldukça uygundur.
2. Proje Kurulumu - Spring Initializr
- Spring Initializr (https://start.spring.io/) kullanarak proje oluşturun.
- Maven ya da Gradle seçimi yapın. Grup, proje adı gibi bilgileri doldurun.
- Bağımlılık olarak: Spring Web, Spring Data JPA, H2 Database vb. seçin.
- Proje Kurulumu - Spring Initializr
- Spring Initializr'ı Kullanarak Proje Oluşturma:
- Spring Initializr (https://start.spring.io/) üzerinden Spring Boot projesi oluşturabilirsiniz.
- Burada grup adı (Group), proje adı (Artifact), proje açıklaması (Description), ve paket adı (Package Name) gibi bilgileri girerek temel proje ayarlarını yapabilirsiniz.
- Maven veya Gradle Seçimi:
- Maven ya da Gradle gibi build araçlarını seçin. Maven, daha yaygın kullanılan bir araçtır, ancak Gradle daha esnek ve performanslıdır. Tercihinize göre birini seçebilirsiniz.
- Spring Boot Versiyonu:
- Projeyi oluştururken kullanmak istediğiniz Spring Boot versiyonunu seçin. Genelde en son kararlı sürümü seçmek iyi bir tercihtir.
- Bağımlılıklar (Dependencies):
- Projeniz için gerekli olan Spring Boot modüllerini ekleyin. Mikroservis, web tabanlı bir uygulama ya da veri tabanı işlemleri yapacaksanız aşağıdaki bağımlılıkları seçebilirsiniz:
- Spring Web: Web uygulamaları geliştirmek için gerekli bağımlılık. RESTful API'ler oluşturmak için kullanılır.
- Spring Data JPA: Veri tabanı işlemleri ve JPA (Java Persistence API) entegrasyonu için kullanılır.
- H2 Database: Hafif, yerleşik bir veri tabanı. Geliştirme ve test amaçlı kullanılır.
- Spring Boot DevTools: Geliştirme sürecinde uygulamanın otomatik yeniden başlatılması ve hızlı gelişim için devtools modülünü ekleyebilirsiniz.
- Projeyi İndirin ve Çalıştırın:
- Bilgileri doldurduktan sonra “Generate” butonuna tıklayarak projeyi indirin.
- İndirdiğiniz ZIP dosyasını açın ve IDE'nize (IntelliJ IDEA, Eclipse vb.) aktarın.
- Maven ya da Gradle kullanıyorsanız, projenizin bağımlılıklarını indirip yapılandırın.
- Proje Başlatma:
- Main sınıfını çalıştırarak Spring Boot uygulamanızı başlatabilirsiniz. @SpringBootApplication anotasyonu ile uygulamanız otomatik olarak başlatılır.
Örnek Maven Bağımlılıkları (pom.xml):
<dependencies>
<!-- Spring Web Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- H2 Database -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Spring Boot DevTools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- Spring Boot Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Bu adımları tamamladıktan sonra Spring Boot projeniz çalışmaya hazır olacaktır!
3. Spring Boot Ana Sınıfı
- 3. Spring Boot Ana Sınıfı
- Spring Boot uygulamalarında, ana sınıf uygulamanın giriş noktasıdır ve @SpringBootApplication anotasyonu ile tanımlanır. Bu anotasyon, bir Spring Boot uygulamasını başlatmak için gereken yapılandırmaları otomatik olarak sağlar.
@SpringBootApplication Anotasyonu:
- @SpringBootApplication, üç önemli anotasyonu bir araya getirir:
- @Configuration: Uygulamanın yapılandırmasını belirtir ve Spring IoC container'a bean'leri tanıtır.
- @EnableAutoConfiguration: Spring Boot'un otomatik yapılandırma özelliğini etkinleştirir, yani projenizdeki bağımlılıklara göre varsayılan konfigürasyonları yükler.
- @ComponentScan: Projedeki bileşenlerin (controller, service, repository gibi) taranmasını ve Spring container'a eklenmesini sağlar.
Spring Boot Ana Sınıfı Nasıl Oluşturulur:
- Aşağıdaki kod örneği, bir Spring Boot uygulamasının ana sınıfını gösterir. Uygulamanızın başladığı yer burasıdır ve SpringApplication.run() metodu ile Spring konteyner'ını başlatarak uygulamayı çalıştırır.
Örnek Spring Boot Ana Sınıfı:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Açıklamalar:
- @SpringBootApplication: Bu anotasyon sayesinde Spring Boot, uygulamanızın ana yapılandırmasını otomatik olarak başlatır.
- main() metodu: Bu metot Java uygulamalarında giriş noktasıdır. SpringApplication.run() metodu ile Spring Boot uygulaması başlatılır. Bu metot uygulamanızın tüm bileşenlerini (controller, service, repository gibi) çalıştırır.
- DemoApplication sınıfı: Ana sınıf, genellikle uygulamanızın en üst seviye yapılandırmalarını içerir. Spring Boot uygulamanızın kalbidir.
Uygulamanın Başlatılması:
- Bu ana sınıfı çalıştırdığınızda Spring Boot, uygulamanızın temel yapılandırmalarını otomatik olarak yapar ve yerleşik bir sunucu (Tomcat gibi) üzerinde uygulamanızı çalıştırır. Uygulamanız artık http://localhost:8080 adresinde hizmet verir.
Spring Boot'un bu sade yapısı, minimal kod ile hızlı bir şekilde projeler geliştirmenizi sağlar.
4. Controller Oluşturma
- 4. Controller Oluşturma
Spring Boot'ta Controller, gelen HTTP isteklerini karşılayan ve uygun yanıtları dönen sınıflardır. RestController sınıfı, RESTful API geliştirmede kullanılır ve HTTP isteğini karşılayıp JSON veya metin tabanlı bir yanıt döner.
@RestController ve @RequestMapping Anotasyonları:
- @RestController: Bu anotasyon, bir sınıfın RESTful web hizmetleri için bir controller olduğunu belirtir. Yanıtlar otomatik olarak JSON, XML veya düz metin gibi uygun bir formatta döner.
- @RequestMapping: Bu anotasyon, sınıf veya metot üzerinde kullanılarak hangi URL'lerin bu controller tarafından karşılanacağını belirtir. Hem sınıf hem de metot seviyesinde kullanılabilir.
İlk RestController Sınıfınızı Oluşturma:
Aşağıdaki örnekte, basit bir HelloController sınıfı ile "Hello, Spring Boot!" mesajını dönen bir RESTful API oluşturuyoruz.
Örnek RestController:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
}
Açıklamalar:
- @RestController: Bu sınıfın bir REST API controller'ı olduğunu belirtir. Bu sayede JSON, XML veya düz metin formatında yanıtlar döner.
- @RequestMapping("/api"): Tüm bu sınıftaki URL'lerin /api yolu üzerinden çalışacağını belirtir. Yani bu controller’daki tüm endpoint'ler /api ile başlar.
- @GetMapping("/hello"): Bu metot bir GET HTTP isteği olduğunda çalışır. URL'de /api/hello yoluna GET isteği yapıldığında, "Hello, Spring Boot!" mesajı döner.
- hello() metodu: Bu basit metodun döndüğü string yanıtı, kullanıcıya düz metin olarak iletilir.
Controller'ı Test Etme:
- Uygulamanızı başlattıktan sonra, tarayıcınızda veya Postman gibi bir API test aracı kullanarak şu URL'yi ziyaret edebilirsiniz: http://localhost:8080/api/hello
- Yanıt olarak şu mesajı görmelisiniz: Hello, Spring Boot!
Diğer HTTP Metotları:
- @PostMapping: POST isteği için.
- @PutMapping: PUT isteği için.
- @DeleteMapping: DELETE isteği için.
Bu basit örnekle, Spring Boot'ta bir RESTful API'nin temelini nasıl oluşturacağınızı öğrendiniz.
5. Properties Dosyası (application.properties)
- 5. Properties Dosyası (application.properties)
Spring Boot uygulamaları, yapılandırmalarını merkezi bir yerde toplamak için genellikle application.properties veya application.yml dosyalarını kullanır. Bu dosyalar, uygulamanın çeşitli ayarlarını yapılandırmanıza ve çalıştırmanıza olanak tanır. Varsayılan olarak application.properties dosyası, src/main/resources dizini altında bulunur.
application.properties Dosyasına Konfigürasyon Eklemek:
Aşağıda bir Spring Boot uygulaması için bazı temel ayarları nasıl yapılandıracağınızı gösteren örnek:
# Sunucu yapılandırması
server.port=8081 # Uygulamanın çalışacağı port numarası (varsayılan 8080)
# Veri tabanı yapılandırması (H2 Veri tabanı)
spring.datasource.url=jdbc:h2:mem:testdb # H2 yerleşik bellek içi veri tabanı
spring.datasource.driverClassName=org.h2.Driver # H2 veri tabanı sürücüsü
spring.datasource.username=sa # Varsayılan kullanıcı adı
spring.datasource.password= # Varsayılan şifre boş
spring.h2.console.enabled=true # H2 konsolunu etkinleştirir
spring.h2.console.path=/h2-console # H2 konsoluna erişim yolu
# Hibernate yapılandırması
spring.jpa.hibernate.ddl-auto=update # Veri tabanı şemasını otomatik olarak günceller
spring.jpa.show-sql=true # Konsolda SQL sorgularını gösterir
Açıklamalar:
- server.port=8081: Uygulamanın çalışacağı portu yapılandırır. Varsayılan port 8080'dir, ancak bunu değiştirmek için server.port kullanabilirsiniz. Bu örnekte portu 8081 olarak değiştirdik.
- spring.datasource.url=jdbc:h2:mem:testdb: H2 veri tabanı kullanıyorsanız, bellek içi bir veri tabanı oluşturur. Testler ve geliştirme ortamları için uygundur.
- spring.datasource.driverClassName=org.h2.Driver: H2 veri tabanının Java sürücüsünü belirtir.
- spring.datasource.username ve spring.datasource.password: Veri tabanı için kullanıcı adı ve şifre ayarlarını tanımlar. H2 için genellikle varsayılan olarak sa kullanıcı adı kullanılır ve şifre boş bırakılır.
- spring.h2.console.enabled=true: H2 veri tabanı için yerleşik web konsolunu etkinleştirir. Bu, veri tabanındaki tablo ve verileri tarayıcıda görüntülemenize olanak tanır.
- spring.h2.console.path=/h2-console: H2 konsoluna erişim yolunu belirtir. Uygulamanız çalıştığında, http://localhost:8081/h2-console adresinden erişebilirsiniz.
- spring.jpa.hibernate.ddl-auto=update: Bu ayar, veri tabanı şemasının otomatik olarak güncellenmesini sağlar. Geliştirme ortamı için uygundur.
- update: Şemayı günceller ancak mevcut veriyi korur.
- create: Her seferinde yeni bir şema oluşturur (veriler silinir).
- validate: Şemayı kontrol eder ancak değiştirmez.
- spring.jpa.show-sql=true: Bu ayar, veri tabanı sorgularını konsolda görmenizi sağlar. Uygulamanızın nasıl SQL sorguları oluşturduğunu izlemek için faydalıdır.
application.properties Dosyasını Kullanma:
- application.properties dosyasına eklenen bu ayarlar, uygulamanın davranışını değiştirir ve farklı ortamlara göre yapılandırma yapmanıza olanak tanır.
- Uygulamanızı başlattıktan sonra http://localhost:8081/h2-console adresine giderek H2 veri tabanı konsoluna erişebilirsiniz. Veri tabanına bağlanırken jdbc:h2:mem:testdb adresini kullanabilirsiniz.
Bu yapılandırma ile Spring Boot uygulamanızın port numarasını değiştirdik, veri tabanını yapılandırdık ve SQL sorgularını takip etmeyi etkinleştirdik.
6. Yapılandırma Anotasyonları
- @Configuration, @ComponentScan, @Bean anotasyonlarını öğrenin ve kullanın.
6. Yapılandırma Anotasyonları
Spring Boot’ta, uygulamanın yapılandırmasını sağlamak ve bağımlılıkları yönetmek için birkaç temel anotasyon kullanılır. Bu anotasyonlar, uygulamanızın modüler ve esnek olmasını sağlar. En yaygın kullanılan yapılandırma anotasyonları @Configuration, @ComponentScan, ve @Bean'dir.
1. @Configuration Anotasyonu
- @Configuration, Spring’in IoC (Inversion of Control) konteyneri tarafından yönetilen bean’leri tanımlayan sınıfları belirtmek için kullanılır. Bu sınıf, Java tabanlı yapılandırmaların tanımlanmasını sağlar.
- @Configuration, XML tabanlı konfigürasyon yerine Java sınıflarında yapılandırma yapılmasını sağlar.
Örnek:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyService(); // MyService, Spring tarafından yönetilen bir bean olacaktır
}
}
- Bu örnekte, AppConfig sınıfı bir konfigürasyon sınıfı olarak belirtilmiştir. İçinde bir myService adında bean tanımlanmıştır.
2. @ComponentScan Anotasyonu
- @ComponentScan, Spring’in belirli bir paket ve onun alt paketlerinde @Component, @Service, @Repository, @Controller gibi anotasyonlar ile tanımlanan sınıfları otomatik olarak tarayıp Spring IoC konteyner'ına eklemesini sağlar.
- Varsayılan olarak, @SpringBootApplication anotasyonu, ana sınıfın bulunduğu paketi ve alt paketlerini tarar. Ancak, uygulamanızın belirli bir paketteki bileşenleri bulmasını sağlamak için manuel olarak @ComponentScan kullanabilirsiniz.
Örnek:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.example.services") // Belirli bir paketi tarar
public class AppConfig {
// Diğer konfigürasyonlar burada yer alabilir
}
- Bu örnekte, com.example.services paketindeki tüm bileşenler taranacak ve Spring IoC konteyner'ına eklenecektir.
3. @Bean Anotasyonu
- @Bean, Spring IoC konteynerına elle bean tanımlamak için kullanılır. @Bean metot seviyesinde kullanılır ve bir metotun geri döndüğü nesnenin Spring IoC tarafından bir bean olarak yönetileceğini belirtir.
- @Bean anotasyonu genellikle @Configuration ile birlikte kullanılır, ancak diğer Spring bileşenleri ile de kullanılabilir.
Örnek:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyService(); // MyService bean olarak tanımlandı
}
@Bean
public MyRepository myRepository() {
return new MyRepository(); // MyRepository bean olarak tanımlandı
}
}
- Bu örnekte, myService ve myRepository Spring tarafından yönetilen bean'ler olarak tanımlanmıştır. Spring IoC bu bean'leri gerektiğinde enjekte edecektir.
Kullanım Senaryosu:
Bu anotasyonlar, Spring uygulamalarını modüler hale getirir ve yapılandırmaları yönetmeyi kolaylaştırır. @Configuration sınıfında tanımlanan @Bean'ler, uygulamanın çeşitli bileşenlerine bağımlılık enjeksiyonu ile aktarılabilir. @ComponentScan ile ise belirli bir paket ve alt paketler taranarak otomatik olarak bileşenler yüklenir.
Özet:
- @Configuration: Java tabanlı yapılandırma sınıfı olduğunu belirtir.
- @ComponentScan: Belirtilen paket ve alt paketlerde Spring bileşenlerini otomatik olarak tarar.
- @Bean: Bir metot seviyesinde kullanılır ve geri döndüğü nesnenin bir Spring bean'i olacağını belirtir.
Bu yapılandırma anotasyonları, uygulamanızın daha temiz ve yapılandırılabilir olmasını sağlar.
7. Dependency Injection (Bağımlılık Enjeksiyonu)
- 7. Dependency Injection (Bağımlılık Enjeksiyonu)
Spring Framework'ün temel özelliklerinden biri Inversion of Control (IOC) ve Dependency Injection (Bağımlılık Enjeksiyonu)'dur. Bu yaklaşım, sınıflar arasındaki bağımlılıkları Spring IoC konteyneri aracılığıyla yönetir ve gerekli sınıfların otomatik olarak enjekte edilmesini sağlar.
Bağımlılık Enjeksiyonu, bir sınıfın başka bir sınıfa olan bağımlılığını manuel olarak oluşturmak yerine, Spring tarafından otomatik olarak enjekte edilmesi anlamına gelir. Bu, kodun daha esnek, yeniden kullanılabilir ve test edilebilir olmasını sağlar.
Temel Bağımlılık Enjeksiyonu
Spring’de bağımlılık enjeksiyonunu genellikle aşağıdaki anotasyonlar aracılığıyla kullanırız:
- @Autowired: Bağımlılıkların otomatik olarak enjekte edilmesini sağlar.
- @Service, @Repository, @Component, @Controller: Bu anotasyonlar, sınıfları Spring IoC konteynerine tanıtarak, Spring’in bu sınıfları yönetmesini sağlar.
Örnek: @Service ve @Autowired Kullanarak Bağımlılık Enjeksiyonu
Aşağıda, MyService sınıfı bir service olarak işaretlenmiş ve MyController sınıfında bu service otomatik olarak enjekte edilmiştir.
1. MyService (Servis Sınıfı):
import org.springframework.stereotype.Service;
@Service
public class MyService {
public String serviceMethod() {
return "Service running";
}
}
- @Service anotasyonu, bu sınıfın bir Spring bileşeni olduğunu ve Spring IoC konteynerı tarafından yönetileceğini belirtir.
- serviceMethod() isimli bir metot, basit bir işlem yapar ve "Service running" mesajını döner.
2. MyController (Controller Sınıfı):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class MyController {
private final MyService myService;
@Autowired // Bağımlılığın enjekte edilmesini sağlar
public MyController(MyService myService) {
this.myService = myService;
}
@GetMapping("/runService")
public String runService() {
return myService.serviceMethod();
}
}
Açıklamalar:
- @Autowired: Bu anotasyon ile Spring, MyService sınıfını otomatik olarak MyController sınıfına enjekte eder. Bu sayede MyController, MyService'e bağımlı olur, ancak manuel olarak oluşturmak yerine Spring tarafından yönetilir.
- Bağımlılık Enjeksiyonu: MyController sınıfı, MyService sınıfına bağımlıdır, ancak bu bağımlılığı Spring yönetir ve gerekli olduğunda MyService bean'ini oluşturup MyController'a enjekte eder.
- Constructor Injection: En yaygın bağımlılık enjeksiyonu yöntemlerinden biri constructor enjeksiyonudur. Bu yöntem, bağımlılıkları sınıfın constructor'ında alır ve test edilebilirliği artırır. Field Injection yerine constructor enjeksiyonunu tercih etmek daha güvenlidir.
Dependency Injection Çalışma Şekli:
- Inversion of Control (IoC): Spring, bağımlılıkları otomatik olarak yönetir ve kontrol eder. Yani, sınıflarınızın bağımlılıklarını manuel olarak oluşturmanız gerekmez; Spring bunu sizin için yapar. Bu, kontrolün tersine çevrilmesi (Inversion of Control) anlamına gelir.
Kullanım:
- Uygulamanızı başlattıktan sonra /api/runService adresine GET isteği gönderdiğinizde, MyController sınıfı aracılığıyla MyService sınıfının serviceMethod() metodunu çağırır ve "Service running" mesajını döner.
Diğer Yöntemler:
- Setter Injection: Bağımlılıkları setter metotları aracılığıyla enjekte etmek.
- Field Injection: Alan seviyesinde (değişken seviyesinde) enjeksiyon. Bu yöntem yaygın olsa da, test edilebilirlik ve esneklik açısından constructor enjeksiyon tercih edilmelidir.
Özet:
- Bağımlılık Enjeksiyonu: Bir sınıfın başka bir sınıfa olan bağımlılığı Spring IoC konteyneri tarafından yönetilir.
- @Autowired: Spring, ilgili bağımlılıkları otomatik olarak enjekte eder.
- @Service, @Repository, @Component: Bu anotasyonlar sınıfların Spring tarafından yönetilen bean'ler olduğunu belirtir.
Bu yapı, Spring Boot uygulamalarında bağımlılıkların yönetilmesini otomatik hale getirir ve kodunuzu daha modüler, esnek ve test edilebilir yapar.
8. Spring Boot DevTools Kullanımı
- 8. Spring Boot DevTools Kullanımı
Spring Boot DevTools, geliştirme sürecinde geliştirmeleri hızlandırmak için kullanılır. En önemli özelliği, kodda yapılan değişiklikleri algılayarak uygulamanızı otomatik olarak yeniden başlatmasıdır. Bu, her kod değişikliğinden sonra uygulamayı manuel olarak yeniden başlatmak zorunda kalmadan hızlı bir geliştirme döngüsü sağlar.
DevTools’un Başlıca Özellikleri:
- Otomatik Yeniden Başlatma (Automatic Restart): Kod değişikliklerini algılayarak uygulamanın yeniden başlatılmasını sağlar.
- LiveReload: Tarayıcıda sayfanın otomatik olarak yenilenmesini sağlar (LiveReload eklentisiyle).
- Hızlı Uygulama Başlatma: Geliştirme modunda uygulama daha hızlı başlatılır.
- Özel Geliştirme ve Üretim Yapılandırması: application.properties içinde geliştirme ve üretim yapılandırmalarını ayırt edebilir.
- Önbellek Devre Dışı Bırakma: Thymeleaf gibi şablonlar için önbellekleme işlemlerini geliştirirken devre dışı bırakır.
Spring Boot DevTools Bağımlılığını Ekleme
Maven kullanıyorsanız, DevTools bağımlılığını pom.xml dosyanıza şu şekilde ekleyebilirsiniz:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
Gradle kullanıyorsanız, build.gradle dosyasına şu satırı ekleyebilirsiniz:
implementation 'org.springframework.boot:spring-boot-devtools'
Önemli Not:
- DevTools bağımlılığı yalnızca geliştirme ortamında çalışır. Üretim ortamında otomatik olarak devre dışı bırakılır.
- Bu bağımlılık, uygulamanın .jar dosyası üretildiğinde veya dağıtıldığında dahil edilmez. Yani üretim ortamında performansı etkilemez.
Otomatik Yeniden Başlatma Özelliği:
Spring Boot DevTools'un sağladığı automatic restart özelliği, sadece sınıf dosyalarında (Java, Kotlin vb.) yapılan değişikliklerde uygulamayı yeniden başlatır. Yeniden başlatma işlemi, eski uygulama verilerini korur, bu yüzden hızlı ve etkili bir yöntemdir. Örneğin:
- Eğer Controller, Service, Repository veya başka bir sınıfta değişiklik yaparsanız, uygulama bu değişiklikleri otomatik olarak algılar ve uygulamanızı yeniden başlatır.
LiveReload Kullanımı:
LiveReload, tarayıcıdaki sayfanın otomatik olarak yenilenmesini sağlayan bir özelliktir. LiveReload eklentisini tarayıcınıza kurarak, uygulamada yapılan HTML, CSS veya JavaScript gibi değişiklikleri otomatik olarak görebilirsiniz. Tarayıcıda sayfayı manuel olarak yenilemek zorunda kalmadan güncellemeleri anında görebilirsiniz.
application.properties Ayarları:
application.properties dosyanıza ekleyebileceğiniz bazı DevTools ayarları:
# DevTools otomatik yeniden başlatmayı etkinleştirir (varsayılan olarak true)
spring.devtools.restart.enabled=true
# LiveReload etkinleştirir
spring.devtools.livereload.enabled=true
# Şablon motorları (Thymeleaf gibi) için önbellekleme devre dışı bırakılır
spring.thymeleaf.cache=false
DevTools ile Geliştirme Sürecini Hızlandırma:
- Uygulama geliştirirken Spring Boot DevTools’u kullanarak kodda yaptığınız değişikliklerin anında devreye girmesini sağlayabilirsiniz.
- Thymeleaf, CSS veya JavaScript gibi statik dosyalarda yapılan değişiklikleri görmek için sayfayı manuel olarak yenilemeden tarayıcıda anında görebilirsiniz.
Özet:
- Spring Boot DevTools, geliştirme sürecini hızlandıran bir bağımlılıktır.
- Otomatik yeniden başlatma, LiveReload gibi özelliklerle kodda yapılan değişikliklerin anında uygulamada görünmesini sağlar.
- Üretim ortamında devre dışıdır, sadece geliştirme sürecinde kullanılır.
Spring Boot DevTools, Spring Boot uygulamalarınızı geliştirirken size daha hızlı bir geliştirme döngüsü sağlar ve verimliliğinizi artırır.
### 9. **Model (Entity) Sınıfı Oluşturma**
- JPA ile bir **Entity** sınıfı oluşturun:
```java
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
// Getters, Setters
}
10. JPA Repository Kullanımı
- CrudRepository ya da JpaRepository kullanarak veri tabanı işlemleri yapın:
- public interface ProductRepository extends JpaRepository<Product, Long> {
- }
10. JPA Repository Kullanımı
Spring Data JPA, veri tabanı işlemlerini kolayca yönetmek için JpaRepository, CrudRepository gibi hazır arayüzler sunar. Bu arayüzler, veri tabanı üzerinde CRUD (Create, Read, Update, Delete) işlemleri yapmayı büyük ölçüde basitleştirir ve bu işlemleri gerçekleştirirken neredeyse hiç SQL kodu yazmanıza gerek kalmaz.
CrudRepository ve JpaRepository Farkı:
- CrudRepository: Tüm temel CRUD (Create, Read, Update, Delete) işlemleri için metotlar içerir. Daha temel bir arayüzdür.
- JpaRepository: CrudRepository'nin tüm özelliklerini içerir ve ayrıca daha gelişmiş özellikler (pagination, sorting vb.) sağlar. Genellikle daha fazla fonksiyon içerdiği için tercih edilir.
Örnek Senaryo: JpaRepository Kullanarak Veri Tabanı İşlemleri Yapma
Aşağıda, bir Product varlığı (entity) için CRUD işlemlerini gerçekleştiren basit bir ProductRepository örneği göreceksiniz.
1. Product Entity Sınıfı
- İlk olarak, veri tabanında saklanacak olan varlığı (entity) oluşturmalısınız.
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
- @Entity: Bu anotasyon, bu sınıfın bir veri tabanı tablosuna eşleneceğini belirtir.
- @Id ve @GeneratedValue: id alanı bu tablodaki her kaydın benzersiz anahtarıdır ve veri tabanında otomatik olarak oluşturulur.
2. JpaRepository Arayüzü ile CRUD İşlemleri
ProductRepository sınıfı, JpaRepository'yi genişleterek temel CRUD işlemlerini gerçekleştirebilir.
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
}
- JpaRepository<Product, Long>: Product sınıfı üzerinde CRUD işlemleri gerçekleştiren bir arayüzdür. Burada Product entity'si ve entity'nin ID tipi Long olarak tanımlanmıştır.
- @Repository: Bu anotasyon, Spring'e bu sınıfın bir veri erişim bileşeni olduğunu belirtir. Ancak Spring Data JPA, @Repository anotasyonu olmadan da repository'yi otomatik olarak algılar.
3. Service Katmanı
Repository'yi kullanarak iş mantığını yönetmek için bir Service sınıfı oluşturabilirsiniz.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ProductService {
private final ProductRepository productRepository;
@Autowired
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
public List<Product> getAllProducts() {
return productRepository.findAll();
}
public Product saveProduct(Product product) {
return productRepository.save(product);
}
public Product getProductById(Long id) {
return productRepository.findById(id).orElse(null);
}
public void deleteProduct(Long id) {
productRepository.deleteById(id);
}
}
- findAll(): Tüm Product kayıtlarını getirir.
- save(): Yeni bir Product kaydeder veya mevcut olanı günceller.
- findById(): ID ile bir Product getirir.
- deleteById(): ID ile bir Product siler.
4. Controller Katmanı
Son olarak, HTTP isteklerini işlemek için bir Controller sınıfı oluşturabilirsiniz.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/products")
public class ProductController {
private final ProductService productService;
@Autowired
public ProductController(ProductService productService) {
this.productService = productService;
}
@GetMapping
public List<Product> getAllProducts() {
return productService.getAllProducts();
}
@PostMapping
public Product createProduct(@RequestBody Product product) {
return productService.saveProduct(product);
}
@GetMapping("/{id}")
public Product getProductById(@PathVariable Long id) {
return productService.getProductById(id);
}
@DeleteMapping("/{id}")
public void deleteProduct(@PathVariable Long id) {
productService.deleteProduct(id);
}
}
- @GetMapping: Tüm ürünleri getirir (GET /api/products).
- @PostMapping: Yeni bir ürün oluşturur (POST /api/products).
- @GetMapping("/{id}"): ID'ye göre bir ürünü getirir (GET /api/products/{id}).
- @DeleteMapping("/{id}"): ID'ye göre bir ürünü siler (DELETE /api/products/{id}).
5. Veri Tabanı Yapılandırması (H2)
application.properties dosyanıza H2 veri tabanı yapılandırmasını ekleyin:
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=update
spring.h2.console.enabled=true
Uygulamanın Çalıştırılması:
- Uygulamanızı başlattıktan sonra http://localhost:8080/api/products adresine GET isteği göndererek tüm ürünleri listeleyebilir ya da Postman gibi bir araçla POST isteği yaparak yeni bir ürün oluşturabilirsiniz.
Özet:
- JpaRepository ve CrudRepository, veri tabanı işlemlerini kolaylaştırır ve CRUD operasyonları için ihtiyacınız olan tüm temel metotları sağlar.
- Spring Data JPA, repository'leri otomatik olarak yönetir ve bu repository'leri kullanarak veri tabanı işlemlerini basit bir şekilde gerçekleştirebilirsiniz.
11. Veri Tabanı Yapılandırması
- H2 ya da MySQL gibi bir veri tabanı yapılandırın.
11. Veri Tabanı Yapılandırması
Spring Boot uygulamalarında veri tabanı yapılandırması oldukça basittir. Spring Boot, H2 gibi yerleşik veri tabanlarını kullanarak hızlı geliştirme yapmanızı sağlarken, MySQL gibi daha büyük veri tabanlarıyla da entegrasyon sağlar.
Aşağıda hem H2 hem de MySQL veri tabanlarının nasıl yapılandırılacağını açıklıyorum:
1. H2 Veri Tabanı Yapılandırması
H2, Spring Boot uygulamalarında yerleşik olarak kullanılan hafif, bellek içi bir veri tabanıdır. Geliştirme ve test işlemleri için oldukça kullanışlıdır. Hafif olduğu için hızlıca kurulum yaparak kullanabilirsiniz.
H2 Bağımlılığı (pom.xml):
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
application.properties ile H2 Yapılandırması:
# H2 veri tabanı yapılandırması
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
# Hibernate yapılandırması (JPA)
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
- spring.datasource.url=jdbc:h2:mem:testdb: H2 için bellek içi bir veri tabanı kullanılır. Her uygulama başlatıldığında temiz bir veri tabanı ile başlar.
- spring.h2.console.enabled=true: H2 için bir web konsolu sağlar. Bu konsolu kullanarak veri tabanını tarayıcı üzerinden yönetebilirsiniz.
- spring.h2.console.path=/h2-console: H2 konsoluna /h2-console yolundan erişebilirsiniz.
- spring.jpa.hibernate.ddl-auto=update: Bu ayar, JPA'nın veri tabanı tablolarını otomatik olarak oluşturup güncellemesine olanak tanır.
H2 Konsoluna Erişim:
- Uygulamanız çalışırken, tarayıcınızda http://localhost:8080/h2-console adresine gidin.
- Veri tabanı URL’si olarak jdbc:h2:mem:testdb'yi kullanarak konsola giriş yapabilirsiniz.
Özet:
- H2, geliştirme ve test için hızlıca kurulabilen hafif bir veri tabanıdır.
- Konsol arayüzü ile veri tabanını yönetmek oldukça kolaydır.
————————
2. MySQL Veri Tabanı Yapılandırması
MySQL, yaygın olarak kullanılan, güçlü ve yüksek performanslı bir veri tabanıdır. Spring Boot ile MySQL kullanarak kalıcı verilerle çalışabilirsiniz.
MySQL Bağımlılığı (pom.xml):
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
application.properties ile MySQL Yapılandırması:
# MySQL veri tabanı yapılandırması
spring.datasource.url=jdbc:mysql://localhost:3306/your_database_name?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=your_password
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
# Hibernate yapılandırması (JPA)
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
- spring.datasource.url=jdbc:mysql://localhost:3306/your_database_name: MySQL sunucusuna bağlanmak için URL yapısı. your_database_name kısmını kendi veri tabanı isminizle değiştirmelisiniz.
- spring.datasource.username=root ve spring.datasource.password=your_password: MySQL sunucusundaki kullanıcı adı ve şifreniz.
- spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver: MySQL JDBC sürücüsü.
- spring.jpa.hibernate.ddl-auto=update: JPA'nın veri tabanı şemasını otomatik güncellemesini sağlar. İlk çalıştırmada tabloları otomatik olarak oluşturur.
- spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect: MySQL veri tabanı ile uyumlu bir Hibernate dilini belirtir.
MySQL Veri Tabanı Oluşturma:
MySQL'de uygulamanızın kullanacağı veri tabanını manuel olarak oluşturmanız gerekebilir:
CREATE DATABASE your_database_name;
Ardından, Spring Boot uygulamanız yukarıda belirttiğiniz veri tabanına bağlanır ve tabloları otomatik olarak oluşturur.
MySQL ile Bağlantı Problemleri:
- Eğer MySQL'e bağlanırken sorun yaşıyorsanız, aşağıdaki adımları kontrol edin:
- MySQL servisinin çalışır durumda olduğundan emin olun.
- MySQL'de doğru portu (varsayılan 3306) kullandığınızdan emin olun.
- MySQL sürümünüze uygun Dialect ayarını kontrol edin.
Özet:
- MySQL, büyük ve kalıcı verilerle çalışmak için ideal bir veri tabanıdır.
- Spring Boot, MySQL ile kolayca entegre olabilir ve veri tabanı işlemlerini sorunsuz bir şekilde gerçekleştirebilir.
————————
Hangi Veri Tabanı Ne Zaman Kullanılmalı?
- H2: Geliştirme ve test süreçlerinde, hızlı kurulum ve hafifliği nedeniyle tercih edilir.
- MySQL: Üretim ortamlarında ve kalıcı veri saklama ihtiyacınız varsa tercih edilmelidir.
Her iki veri tabanı da Spring Boot ile kolayca yapılandırılabilir. Seçiminizi projenizin ihtiyaçlarına göre yapabilirsiniz.
12. Spring Boot Actuator
12. Spring Boot Actuator
Spring Boot Actuator, Spring Boot uygulamalarını izlemek, yönetmek ve sağlık durumu, uygulama metrikleri gibi bilgileri kontrol etmek için kullanılan bir modüldür. Actuator, uygulamanızın iç işleyişini gözlemlemenize yardımcı olur ve üretim ortamlarında uygulamanızı daha güvenli bir şekilde izleyebilmeniz için çeşitli uç noktalar (endpoints) sağlar.
Actuator ile sağlık kontrolü (health checks), metrikler, bean bilgileri, çevresel yapılandırmalar gibi birçok bilgiyi dinamik olarak alabilirsiniz.
Spring Boot Actuator Bağımlılığını Ekleme
Maven kullanıyorsanız, Actuator bağımlılığını pom.xml dosyanıza şu şekilde ekleyin:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Gradle kullanıyorsanız, build.gradle dosyasına şu satırı ekleyin:
implementation 'org.springframework.boot:spring-boot-starter-actuator'
Actuator Özelliklerini Etkinleştirme
Varsayılan olarak, sadece belirli Actuator uç noktaları etkinleştirilmiştir (örneğin, /health ve /info). Daha fazla uç noktayı etkinleştirmek veya yapılandırmak için application.properties dosyasına ayarlar ekleyebilirsiniz.
application.properties ile Actuator Yapılandırması:
# Actuator URL yolunu değiştirme (varsayılan olarak /actuator kullanılır)
management.endpoints.web.base-path=/actuator
# Tüm actuator uç noktalarını etkinleştirir
management.endpoints.web.exposure.include=*
# Sağlık kontrolü detaylarını gösterir
management.endpoint.health.show-details=always
- management.endpoints.web.base-path=/actuator: Actuator uç noktalarının temel yolunu belirtir (varsayılan olarak /actuator yolunu kullanır).
- management.endpoints.web.exposure.include=*: Bu ayar, tüm actuator uç noktalarını (endpoints) etkinleştirir. Belirli uç noktaları etkinleştirmek için sadece istediğiniz uç noktaları virgülle ayırarak ekleyebilirsiniz (örneğin, health,info).
- management.endpoint.health.show-details=always: Sağlık kontrolü (health check) detaylarını her zaman gösterir. Bu, özellikle uygulamanın durumunu (örneğin, veri tabanı bağlantıları) kontrol etmek için faydalıdır.
Actuator Uç Noktalarını Kullanma
Spring Boot Actuator, uygulamanız hakkında bilgi edinmek için bir dizi hazır uç nokta sunar. Uygulamanızı başlattıktan sonra tarayıcıda veya Postman gibi bir araçla bu uç noktaları kullanabilirsiniz.
Yaygın Actuator Uç Noktaları:
- /actuator/health: Uygulamanızın sağlık durumunu kontrol eder. Bu uç nokta, veri tabanı, disk durumu, dış servisler gibi bağımlılıkların sağlıklı olup olmadığını bildirir.
- http://localhost:8080/actuator/health
Örnek Yanıt:
{
"status": "UP"
}
- /actuator/info: Uygulamanız hakkında bilgi döner. application.properties dosyasında belirttiğiniz özel bilgilerle yapılandırılabilir.
- http://localhost:8080/actuator/info
- /actuator/metrics: Uygulamanızın performans metriklerini döner (CPU kullanımı, bellek kullanımı gibi).
- http://localhost:8080/actuator/metrics
- /actuator/env: Uygulamanızın ortam değişkenlerini ve yapılandırma bilgilerini gösterir.
- http://localhost:8080/actuator/env
- /actuator/beans: Spring IoC konteynerındaki bean'lerin listesini döner.
- http://localhost:8080/actuator/beans
- /actuator/loggers: Uygulamadaki log seviyelerini kontrol eder ve değiştirme imkanı sunar.
- http://localhost:8080/actuator/loggers
- /actuator/threaddump: Uygulamanın mevcut thread dump’ını gösterir. Bu, uygulamanın performansını izlemek için faydalıdır.
- http://localhost:8080/actuator/threaddump
Özelleştirilmiş Bilgi (info) Uç Noktası
/actuator/info uç noktası aracılığıyla uygulama hakkında özel bilgiler döndürebilirsiniz. Bunun için application.properties dosyasına özel bilgiler ekleyebilirsiniz:
info.app.name=My Spring Boot Application
info.app.description=This is a sample Spring Boot application using Actuator
info.app.version=1.0.0
/actuator/info uç noktasına istek yaptığınızda, şu şekilde bir yanıt alırsınız:
{
"app": {
"name": "My Spring Boot Application",
"description": "This is a sample Spring Boot application using Actuator",
"version": "1.0.0"
}
}
Sağlık Kontrolleri (Health Checks) ve Metrikler
Spring Boot Actuator, uygulamanızın sağlık durumu ile ilgili birçok metriği otomatik olarak toplar. Örneğin, /actuator/health uç noktasından veri tabanı bağlantısı, mesajlaşma kuyruğu, disk alanı gibi önemli servislerin durumu hakkında bilgi alabilirsiniz.
Eğer uygulamanızda bir veri tabanı bağlıysa, /actuator/health uç noktası veri tabanı durumunu da gösterecektir. Örneğin, H2 ya da MySQL veri tabanı bağlıysa şu şekilde bir yanıt alabilirsiniz:
{
"status": "UP",
"components": {
"db": {
"status": "UP",
"details": {
"database": "H2",
"result": 1
}
},
"diskSpace": {
"status": "UP",
"details": {
"total": 499963174912,
"free": 320593854464,
"threshold": 10485760
}
}
}
}
Özet:
- Spring Boot Actuator, uygulamanızın sağlık durumunu ve performans metriklerini izlemek için kullanışlı uç noktalar sağlar.
- Actuator, üretim ortamında izleme, hata teşhisi ve performans ölçümü gibi görevlerde önemli bir araçtır.
- Uç noktalar, uygulamanız hakkında derinlemesine bilgi verir ve gerektiğinde özelleştirilebilir.
- Özellikle /health ve /metrics uç noktaları, üretim ortamlarında uygulamanızın sağlığını ve performansını izlemek için hayati öneme sahiptir.
Actuator, uygulamanızın sağlıklı çalıştığından emin olmak ve performansını izlemek için güçlü bir çözümdür.
13. Error Handling (Hata Yönetimi)
13. Error Handling (Hata Yönetimi)
Spring Boot uygulamalarında, hata yönetimi önemli bir konudur. Hataları düzgün bir şekilde yakalamak ve kullanıcıya anlamlı hata mesajları döndürmek, uygulamanın güvenilirliğini artırır. Spring, hata yönetimi için @ExceptionHandler anotasyonu ve @ControllerAdvice gibi araçlar sağlar. Bu araçlar, özel durumları (exception) yakalayarak onlara uygun yanıtlar döndürebilmenize olanak tanır.
@ExceptionHandler ile Özel Hata Yönetimi
@ExceptionHandler anotasyonu, bir controller veya global olarak belirli hataları yakalayıp yönetmek için kullanılır. Örneğin, bir kaynak bulunamadığında (404 hatası) özel bir yanıt döndürmek isteyebilirsiniz. Bunun için @ExceptionHandler anotasyonu kullanılır.
Örnek: Kaynak Bulunamadığında Hata Yönetimi
Bir kaynak (örneğin, bir ürün) bulunamadığında, ResourceNotFoundException fırlatabilir ve bu hatayı özel bir şekilde ele alabilirsiniz.
1. Özel İstisna (Exception) Sınıfı
İlk olarak, bir özel hata sınıfı oluşturun:
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
Bu sınıf, RuntimeException sınıfını genişletir ve ResourceNotFoundException hatasını fırlatmak için kullanılır.
2. Controller'da @ExceptionHandler ile Hata Yakalama
Controller sınıfınızda, @ExceptionHandler kullanarak bu özel durumu yakalayabilirsiniz.
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/products")
public class ProductController {
// Ürünleri tutan basit bir liste (örnek amaçlı)
private Map<Long, String> products = new HashMap<>();
@GetMapping("/{id}")
public ResponseEntity<String> getProductById(@PathVariable Long id) {
String product = products.get(id);
if (product == null) {
throw new ResourceNotFoundException("Product not found with id: " + id);
}
return ResponseEntity.ok(product);
}
// Özel hata yakalayıcı
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<?> resourceNotFoundHandler(ResourceNotFoundException ex) {
return ResponseEntity.notFound().build();
}
}
Açıklamalar:
- @ExceptionHandler: Bu anotasyon, ResourceNotFoundException fırlatıldığında yakalanmasını ve uygun bir yanıt döndürülmesini sağlar.
- ResponseEntity.notFound().build(): 404 Not Found HTTP yanıtını döner.
- throw new ResourceNotFoundException("Product not found with id: " + id): İlgili ürün bulunamazsa bu özel hatayı fırlatır.
Bu yapı sayesinde, ürün bulunmadığında kullanıcıya 404 Not Found yanıtı gönderilecektir.
3. Global Exception Handling (Global Hata Yönetimi) - @ControllerAdvice
Eğer uygulamanızdaki tüm controller'lar için global bir hata yönetimi oluşturmak istiyorsanız, @ControllerAdvice anotasyonunu kullanabilirsiniz. Bu anotasyon, uygulamanın her yerinde meydana gelen hataları yakalar ve uygun yanıtlar döndürebilir.
Global Hata Yönetimi Örneği:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<?> handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Error: " + ex.getMessage());
}
// Diğer istisnalar için genel bir yakalayıcı
@ExceptionHandler(Exception.class)
public ResponseEntity<?> handleGlobalException(Exception ex, WebRequest request) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occurred: " + ex.getMessage());
}
}
Açıklamalar:
- @ControllerAdvice: Bu anotasyon, global hata yönetimi sağlar. Tüm controller'larda meydana gelen hatalar burada yakalanır.
- @ExceptionHandler(ResourceNotFoundException.class): ResourceNotFoundException özel hatasını yakalar ve kullanıcıya anlamlı bir hata mesajı ile yanıt verir.
- @ExceptionHandler(Exception.class): Genel olarak yakalanmayan tüm istisnalar için global bir hata yönetimidir ve 500 Internal Server Error yanıtı döner.
4. Hata Yanıtları için Detaylı Bilgi
Kullanıcılara daha detaylı hata mesajları döndürmek için özel bir hata yanıtı sınıfı oluşturabilirsiniz.
Özel Hata Yanıtı Sınıfı:
public class ErrorResponse {
private String message;
private String details;
public ErrorResponse(String message, String details) {
this.message = message;
this.details = details;
}
// Getters and Setters
}
Hata Yanıtını Kullanma:
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> resourceNotFoundHandler(ResourceNotFoundException ex, WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(ex.getMessage(), request.getDescription(false));
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}
Bu örnekte, kullanıcıya daha ayrıntılı bir hata yanıtı gönderilir. Yanıt şu şekilde görünebilir:
{
"message": "Product not found with id: 1",
"details": "uri=/api/products/1"
}
Özet:
- @ExceptionHandler, belirli bir istisna (exception) meydana geldiğinde özel hata yanıtları oluşturmak için kullanılır.
- @ControllerAdvice ile global hata yönetimi sağlayabilir ve uygulamanızın genelinde meydana gelen hataları tek bir yerde yönetebilirsiniz.
- Kullanıcılara anlamlı hata mesajları dönmek, uygulamanızın kullanıcı dostu olmasını sağlar ve hata yönetimi yapısını basitleştirir.
Spring Boot uygulamalarında hata yönetimi, ExceptionHandler ve ControllerAdvice gibi araçlarla oldukça esnek ve güçlü hale gelir.
14. Logging Kullanımı
14. Logging Kullanımı
Loglama, bir uygulamanın çalışma durumunu izlemek, hataları tespit etmek ve performans verilerini kaydetmek için önemli bir tekniktir. Spring Boot, varsayılan olarak SLF4J (Simple Logging Facade for Java) ve Logback kütüphanelerini kullanır. SLF4J, uygulamanızda kullanılacak loglama framework'ü için bir ara yüz sağlar, Logback ise varsayılan loglama framework'ü olarak gelir.
1. SLF4J ve Logback Kütüphaneleri ile Loglama
Spring Boot projelerinde loglama işlemi için ekstra bir bağımlılık eklemenize gerek yoktur. SLF4J ve Logback Spring Boot projeleri için varsayılan olarak entegre edilmiştir. Yani doğrudan loglama işlemlerine başlayabilirsiniz.
2. Loglama için Gerekli Kod:
Aşağıdaki örnekte, SLF4J ile bir log nesnesi oluşturuyoruz ve uygulamada loglama işlemlerini gerçekleştiriyoruz.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class MyService {
private static final Logger logger = LoggerFactory.getLogger(MyService.class);
public void performService() {
logger.info("Service is running");
try {
// Örnek iş mantığı
int result = 10 / 2;
logger.debug("Calculation result: {}", result);
} catch (Exception e) {
logger.error("An error occurred: {}", e.getMessage());
}
}
}
Açıklamalar:
- LoggerFactory.getLogger(MyService.class): Bu satır, MyService sınıfı için bir Logger örneği oluşturur. Bu örnek, uygulamanın her yerinde loglama işlemlerini yönetir.
- logger.info(): Bilgilendirme seviyesinde (INFO) bir mesaj loglar. Genellikle, uygulamanın önemli adımlarını kaydetmek için kullanılır.
- logger.debug(): Debug seviyesinde bir mesaj loglar. Genellikle, geliştirme sürecinde veya hata ayıklama (debugging) sırasında kullanılır.
- logger.error(): Hata (ERROR) seviyesinde bir mesaj loglar. Genellikle, uygulamada meydana gelen hataları kaydetmek için kullanılır.
Log Seviyeleri:
- TRACE: En ayrıntılı log seviyesidir. Çok fazla ayrıntı içerir ve nadiren kullanılır.
- DEBUG: Geliştirici odaklı bilgileri içerir. Geliştirme ve hata ayıklama sırasında kullanılır.
- INFO: Genel bilgi mesajlarıdır. Uygulamanın işleyişini izlemek için kullanılır.
- WARN: Uyarı mesajlarıdır. Bir sorun olasılığı hakkında bilgi verir, ancak uygulama çalışmaya devam eder.
- ERROR: Hatalı durumlar hakkında bilgi verir. Genellikle istisnalar veya kritik hatalar için kullanılır.
2. Logback Yapılandırması
Logback, Spring Boot'un varsayılan loglama framework'üdür. Logback’i yapılandırmak için logback-spring.xml veya logback.xml dosyasını kullanabilirsiniz. Örneğin, loglama çıktısının formatını, seviyesini ve yönlendirilmesini yapılandırabilirsiniz.
logback-spring.xml Dosyası Örneği:
<configuration>
<!-- Console appender - logları konsola yazdırır -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- File appender - logları bir dosyaya yazdırır -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>app-log.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- Her gün yeni bir log dosyası oluşturur -->
<fileNamePattern>app-log-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>7</maxHistory> <!-- En fazla 7 günlük log dosyası saklar -->
</rollingPolicy>
</appender>
<!-- Log seviyeleri ayarı -->
<root level="info">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>
Açıklamalar:
- <appender name="STDOUT">: Konsola log mesajlarını yazdırır. Log mesajları System.out akışına yönlendirilir.
- <appender name="FILE">: Log mesajlarını bir dosyaya yazar. Burada günlük log dosyası tutulur ve her gün yeni bir dosya oluşturulur (app-log-2024-10-30.log gibi).
- <root level="info">: Loglama seviyesini belirtir. Bu örnekte, INFO seviyesindeki ve daha yüksek (WARN, ERROR) log mesajları işlenecektir.
- <pattern>: Log mesajlarının formatını tanımlar. Burada tarih, log seviyesi, logger adı ve mesajın kendisi yer alır.
3. Log Seviyelerini application.properties Dosyasında Belirleme
Log seviyelerini application.properties dosyasında da yapılandırabilirsiniz:
# Genel log seviyesi
logging.level.root=INFO
# Belirli paketler için log seviyeleri
logging.level.org.springframework.web=DEBUG
logging.level.com.example=DEBUG
# Konsol ve dosya için log formatı
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
# Dosya loglama ayarları
logging.file.name=app-log.log
logging.file.max-history=7
- logging.level.root: Tüm uygulama için genel log seviyesini ayarlar.
- logging.level.org.springframework.web=DEBUG: Belirli bir paket veya sınıf için log seviyesini belirler. Bu örnekte, org.springframework.web paketindeki loglar DEBUG seviyesinde olacaktır.
- logging.pattern.console ve logging.pattern.file: Logların konsol ve dosyadaki formatını belirler.
- logging.file.name=app-log.log: Log dosyasının adını belirtir.
- logging.file.max-history=7: Maksimum 7 günlük log dosyasını saklar.
4. Log Mesajlarını Dosyaya Yönlendirme
Yukarıda gösterilen logback-spring.xml veya application.properties yapılandırmalarını kullanarak log mesajlarını dosyaya yazabilirsiniz. Böylece loglar uygulamanın yaşam döngüsü boyunca kaydedilir ve geçmiş loglar incelenebilir.
Özet:
- SLF4J ile loglama işlemlerini yönetir ve Logback varsayılan loglama framework'ü olarak gelir.
- Logback kullanarak logların hangi formatta ve nereye (konsol, dosya) yazılacağını özelleştirebilirsiniz.
- Log seviyelerini ve yapılandırmalarını application.properties ya da logback-spring.xml dosyaları üzerinden yönetebilirsiniz.
- Geliştirme, test ve üretim ortamlarında farklı loglama ayarları yaparak uygulamanızı daha izlenebilir hale getirebilirsiniz.
Loglama, uygulamanızın sağlıklı çalışmasını izlemek, performansı değerlendirmek ve hataları hızlı bir şekilde bulmak için önemli bir araçtır.
15. Spring Boot Test
15. Spring Boot Test
Spring Boot, JUnit ve Mockito kütüphanelerini entegre ederek birim testleri (unit tests) ve entegrasyon testlerini kolayca yazmanızı sağlar. JUnit birim testleri yazmak için en yaygın kullanılan test kütüphanelerinden biridir ve Mockito ise bağımlılıkların (dependencies) sahte nesneler (mock objects) ile taklit edilmesine olanak tanır. Birlikte, Spring Boot uygulamalarının tüm katmanlarını test etmek için güçlü bir kombinasyon sağlarlar.
1. JUnit ve Mockito Bağımlılıklarını Eklemek
Eğer JUnit ve Mockito bağımlılıkları Spring Boot projenizde yoksa, bu bağımlılıkları pom.xml dosyanıza ekleyin:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
spring-boot-starter-test bağımlılığı, JUnit, Mockito, ve diğer test kütüphanelerini içerir.
2. Temel Spring Boot Test Sınıfı
Bir Spring Boot test sınıfı genellikle @SpringBootTest anotasyonu ile işaretlenir ve Spring Boot'un tüm yapılandırmasını yükler. Bu, entegrasyon testleri için kullanılır. JUnit ile testleri çalıştırmak için her test metodu @Test anotasyonu ile işaretlenir.
Örnek 1: Temel Test Sınıfı
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class DemoApplicationTests {
@Test
void contextLoads() {
// Bu test, uygulamanın başlatılıp başlatılmadığını kontrol eder.
}
}
Bu basit test, Spring Boot uygulamanızın başarılı bir şekilde başlatılıp başlatılmadığını kontrol eder. Eğer bir yapılandırma hatası varsa, bu test başarısız olacaktır.
3. Service Katmanı için Birim Test
Gerçek dünyada, sadece uygulamanın başlatılıp başlatılmadığını değil, aynı zamanda iş mantığının doğru çalışıp çalışmadığını test etmek istersiniz. Bunun için, Mockito kullanarak bağımlılıkları sahte nesnelerle (mock) değiştirebilir ve sadece test edilmek istenen sınıfı izole edebilirsiniz.
Örnek 2: Service Sınıfı Testi
Bu örnekte, bir ProductService sınıfını ve onun ProductRepository ile olan bağımlılığını test ediyoruz. ProductRepository'yi Mockito ile sahte nesne olarak kullanacağız.
1. Service Sınıfı
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
public class ProductService {
private final ProductRepository productRepository;
@Autowired
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
public Product getProductById(Long id) {
return productRepository.findById(id).orElse(null);
}
}
2. Repository Sınıfı
import org.springframework.data.jpa.repository.JpaRepository;
public interface ProductRepository extends JpaRepository<Product, Long> {
}
3. JUnit ve Mockito ile Test
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Optional;
public class ProductServiceTest {
@InjectMocks
private ProductService productService; // Test edeceğimiz sınıf
@Mock
private ProductRepository productRepository; // Sahte repository
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this); // Mockito'yu başlat
}
@Test
void testGetProductById() {
// Sahte veri oluşturuyoruz
Product mockProduct = new Product();
mockProduct.setId(1L);
mockProduct.setName("Test Product");
// Mockito'yu kullanarak sahte repository'yi yapılandırıyoruz
when(productRepository.findById(1L)).thenReturn(Optional.of(mockProduct));
// Servis metodunu test ediyoruz
Product product = productService.getProductById(1L);
// Beklenen sonuçları doğruluyoruz
assertEquals(1L, product.getId());
assertEquals("Test Product", product.getName());
}
}
Açıklamalar:
- @InjectMocks: Test edilen sınıfın (bu örnekte ProductService) bağımlılıkları otomatik olarak enjekte edilir.
- @Mock: Sahte nesne oluşturur (bu örnekte ProductRepository). Bu sınıfı gerçek nesne yerine kullanırız.
- MockitoAnnotations.openMocks(this): Mockito'nun anotasyon tabanlı mock'ları başlatmasını sağlar.
- when(...).thenReturn(...): ProductRepository için bir sahte davranış tanımlıyoruz. Eğer findById(1L) çağrılırsa, mockProduct dönecek.
- assertEquals(...): Beklenen sonuç ile gerçek sonucu karşılaştırarak testin doğru çalışıp çalışmadığını kontrol eder.
4. Controller Katmanı için Test
Controller sınıflarını test etmek için Spring Boot'un sunduğu MockMvc sınıfını kullanabilirsiniz. MockMvc, Spring MVC'yi sahte bir ortamda test etmenize olanak tanır.
Örnek 3: Controller Testi
1. Controller Sınıfı
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/{id}")
public ResponseEntity<Product> getProductById(@PathVariable Long id) {
Product product = productService.getProductById(id);
if (product != null) {
return ResponseEntity.ok(product);
} else {
return ResponseEntity.notFound().build();
}
}
}
2. JUnit ve MockMvc ile Test
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.Optional;
import static org.mockito.Mockito.when;
@WebMvcTest(ProductController.class)
public class ProductControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ProductService productService; // Sahte servis
@Test
void testGetProductById() throws Exception {
// Sahte ürün
Product mockProduct = new Product();
mockProduct.setId(1L);
mockProduct.setName("Test Product");
// Servis metodunun nasıl davranacağını belirliyoruz
when(productService.getProductById(1L)).thenReturn(mockProduct);
// MockMvc kullanarak controller'ı test ediyoruz
mockMvc.perform(get("/api/products/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Test Product"));
}
}
Açıklamalar:
- @WebMvcTest: Sadece controller'ı test etmek için kullanılır. Diğer Spring bileşenleri yüklenmez.
- MockMvc: HTTP isteklerini simüle etmek için kullanılır.
- @MockBean: ProductService'i sahte bir nesne olarak tanımlar.
- mockMvc.perform(get(...)): HTTP GET isteği simüle edilir.
- jsonPath("$.name").value("Test Product"): JSON cevabındaki name alanının beklenen değeri test edilir.
Özet:
- JUnit ve Mockito kullanarak Spring Boot uygulamalarının servis, repository ve controller katmanlarını kolayca test edebilirsiniz.
- Mockito bağımlılıkları sahte nesneler (mock objects) ile taklit eder ve bağımlılıkların izolasyonunu sağlar.
- MockMvc ile Spring MVC controller'larını HTTP isteklerini simüle ederek test edebilirsiniz.
16. Profil Yönetimi
- Farklı application-{profile}.properties dosyaları oluşturarak farklı ortamlarda uygulamanızı çalıştırın.
- 16. Profil Yönetimi
Spring Boot, farklı çalışma ortamları (development, test, production gibi) için profil yönetimi sunar. Profiller, uygulamanızın farklı yapılandırma dosyalarını kullanarak farklı ortamlarda çalışmasını sağlar. Her ortam için (geliştirme, test, üretim) farklı yapılandırmalar yapabilir ve bu profilleri etkinleştirerek ortam spesifik ayarlarla uygulamanızı çalıştırabilirsiniz.
Spring Boot’ta profiller, application-{profile}.properties veya application-{profile}.yml dosyaları kullanılarak yönetilir. Ayrıca default profil de oluşturabilirsiniz.
1. Profil Oluşturma
Farklı ortamlara göre Spring Boot uygulamanızın yapılandırmalarını ayırmak için, her profil için ayrı bir properties dosyası oluşturabilirsiniz. Örneğin:
- application.properties: Genel ayarlar (varsayılan yapılandırma).
- application-dev.properties: Geliştirme ortamı için ayarlar.
- application-prod.properties: Üretim ortamı için ayarlar.
Örnek Yapılandırma Dosyaları:
1. application.properties (Genel Yapılandırma):
Bu dosya, varsayılan yapılandırma ayarlarını içerir ve herhangi bir profil belirtilmediğinde kullanılır.
spring.application.name=MyApp
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
2. application-dev.properties (Geliştirme Ortamı):
Bu dosya, geliştirme ortamı için özel ayarlar içerir.
# Geliştirme ortamı veri tabanı
spring.datasource.url=jdbc:mysql://localhost:3306/dev_db
spring.datasource.username=dev_user
spring.datasource.password=dev_password
# Hibernate ayarları
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
3. application-prod.properties (Üretim Ortamı):
Bu dosya, üretim ortamı için özel ayarlar içerir.
# Üretim ortamı veri tabanı
spring.datasource.url=jdbc:mysql://localhost:3306/prod_db
spring.datasource.username=prod_user
spring.datasource.password=prod_password
# Hibernate ayarları
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=false
# Log seviyesi
logging.level.root=WARN
2. Profili Etkinleştirme
Spring Boot, varsayılan olarak application.properties dosyasını kullanır. Ancak belirli bir profil dosyasını etkinleştirerek, o profile ait yapılandırmaları kullanmasını sağlayabilirsiniz.
Profil Etkinleştirmenin Yolları:
- Komut Satırı ile Profil Etkinleştirme:
- Uygulamayı çalıştırırken komut satırından belirli bir profili etkinleştirebilirsiniz:
mvn spring-boot:run -Dspring-boot.run.profiles=dev
veya
java -jar myapp.jar --spring.profiles.active=prod
- application.properties Dosyasında Profil Ayarı:
- Genel yapılandırma dosyanızda aktif bir profil belirleyebilirsiniz:
- spring.profiles.active=dev