Yazının içeriği SOAP ile REST servisler arasındaki farkları, Spring framework ile SpringBoot arasındaki farkları, annotation örnekleri, Hibernate ve Lombok framework kullanımından oluşmaktadır ve örnek bir proje ile sonlanmaktadır. Keyifli okumalar dilerim.

REST (Representational State Transfer), modern web uygulamalarında popüler bir mimari stilidir. Bu blog yazısında, Java Spring Boot kullanarak nasıl bir REST servisi oluşturabileceğinizi adım adım göstereceğim. Ayrıca Spring Boot kullanırken atlanmaması gereken bazı noktalara da dikkat çekeceğim.

1. SOAP Servisler ile REST Servisler Arasındaki Farklar

SOAP (Simple Object Access Protocol) ve REST (Representational State Transfer) servislerinin kendine özgü avantajları vardır. Bunları aşağıdaki şekilde sıralayabiliriz.

  • Veri Formatı:
    SOAP: XML (eXtensible Markup Language) formatını kullanır.
    REST: Genellikle JSON (JavaScript Object Notation) formatını kullanır.
  • Veri Taşıma:
    SOAP: Genellikle HTTP, SMTP, TCP gibi protokolleri kullanır. Veri taşıma için XML’in üzerine bir protokol katmanı eklenmelidir.
    REST: HTTP protokolünü kullanır. Veriler, HTTP metotları (GET, POST, PUT, DELETE) ve URL yapıları ile taşınır.
  • Arayüz ve Tanımlama:
    SOAP: WSDL (Web Services Description Language) dosyalarını kullanarak servislerin tanımlanması ve ara yüzlerin belirlenmesi için ayrıntılı bir yapıya sahiptir.
    REST: HTTP metotlarıyla çalışır. Servislerin ve verilerin tanımlanması için herhangi bir standart belgeye ihtiyaç duymaz.
  • Veri İletişimi:
    SOAP: Güvenlik, bütünlük ve hata yönetimi gibi konularda daha fazla standartlaşmış özelliklere sahiptir.
    REST: HTTP protokolünü kullanarak veri iletimini gerçekleştirir. Basit, hafif ve doğrudan bir iletişim sağlar.

– SOAP servisler, karmaşık ve yapısal olarak tanımlanmış verilerin taşındığı işlemlere yöneliktir. Özellikle, güvenlik, bütünlük ve hata yönetimi gibi konuların önemli olduğu durumlarda tercih edilebilir.
– REST servisler, daha basit ve hafif veri taşıma ihtiyaçları için uygundur. Genellikle, kaynaklar üzerinde CRUD (Create, Read, Update, Delete) operasyonları gerçekleştirmek için kullanılır. Web, mobil ve IoT uygulamaları için tercih edilebilir.

2. Java Spring Framework ile Spring Boot Arasındaki Farklar

Java Spring Framework, geliştiricilere geniş bir yelpazede özellikler sunan kapsamlı bir uygulama çerçevesidir ve Java EE (Enterprise Edition) uygulamalarının geliştirilmesi için kullanılır. Ancak, Spring’in yapılandırma ve başlatma süreçleri karmaşık olabilir. Spring Boot ise, Spring Framework üzerine inşa edilmiş bir projedir ve otomatik yapılandırma, hızlı başlatma seçenekleri sunar. Spring Boot, yazılım geliştirme sürecini hızlandırır.

3 SpringBoot ile Annotation Kullanımı ve Örnekler

Spring Boot, uygulama geliştirmeyi hızlandıran ve yapılandırmayı kolaylaştıran bir dizi özel annotation (işaretçi) sunar. Bu annotation’lar, geliştirdiğimiz uygulamanın davranışını belirlemek ve çeşitli ayarları yapılandırmak için kullanılır. İşte bazı önemli Spring Boot annotation’ları ve işlevleri:

  • @SpringBootApplication: Bu annotation, bir Spring Boot uygulamasının ana sınıfı üzerine eklenir. Uygulamayı başlatmak için kullanılır ve aynı zamanda @Configuration, @EnableAutoConfiguration ve @ComponentScan annotation’larını içerir.
  • @RestController: Bu annotation, bir sınıfın RESTful hizmetler sunan bir kontrolcü sınıf olduğunu belirtir. Herhangi bir HTTP isteğine yanıt verebilecek metotları içeren sınıflara uygulanır.
  • @RequestMapping: Bu annotation, bir metodun veya sınıfın hangi URL’ye ve HTTP metoduyla eşleştiğini belirtir. Örneğin, @RequestMapping(value = “/users”, method = RequestMethod.GET) şeklinde kullanılarak “/users” URL’sine GET isteği yapıldığında ilgili metotun çalışmasını sağlar.
  • @Autowired: Bu annotation, bağımlılıkların otomatik olarak enjekte edilmesini sağlar.
  • @Configuration: Bu annotation, bir sınıfın yapılandırma sınıfı olduğunu belirtir. Bean’leri oluşturmak ve yapılandırmak için kullanılır. Bu annotation’a sahip bir sınıf, @Bean annotation’ı kullanarak bean’lerin oluşturulduğu metodları içermelidir.
  • @EnableAutoConfiguration: Bu annotation, otomatik yapılandırma özelliğini etkinleştirir. Spring Boot, bağımlılıklara ve yapılandırmaya dayanarak uygulamanın çoğu ayarını otomatik olarak yapar.
  • @ComponentScan: Bu annotation, Spring’in bileşen tarama işlemini belirler. Projenin paket yapısını tarayarak bileşenleri bulmasını sağlar. Bu annotation’ı kullanarak Spring, bileşenlerin (kontrolcüler, servisler, vb.) otomatik olarak tanımlanmasını sağlar.
  • @PathVariable: URL’deki değişkenleri işlem metotlarına parametre olarak aktarmak için kullanılır.
  • @RequestParam: HTTP sorgu parametrelerini işlem metotlarına parametre olarak aktarmak için kullanılır.
  • @RequestBody: HTTP isteği gövdesindeki verileri işlem metotlarına parametre olarak aktarmak için kullanılır. Genellikle JSON veya XML formatında gelen verileri deserializasyon için kullanılır.
    @PostMapping("/example")
    public String createExample(@RequestBody ExampleData data) {
    // …
    }
  • @Component: Spring tarafından yönetilen bir bileşen olduğunu belirtmek için kullanılır. Genellikle sınıfların bean olarak tanımlanması için kullanılır.
  • @PostMapping: HTTP POST isteği için bir işlem metotunu işaretlemek için kullanılır.
    – Parametreler:
    – `value` (veya `path`): İsteği işleyecek URL yolunu belirtir. String tipindedir.
    – `consumes`: İsteğin kabul edebileceği medya tiplerini belirtir. String array olarak verilir.
    – `produces`: Yanıtın üretebileceği medya tiplerini belirtir. String array olarak verilir.
  • @GetMapping: HTTP GET isteği için bir işlem metotunu işaretlemek için kullanılır.
    – Parametreler:
    – `value` (veya `path`): İsteği işleyecek URL yolunu belirtir. String tipindedir.
    – `produces`: Yanıtın üretebileceği medya tiplerini belirtir. String array olarak verilir.
  • @PutMapping: HTTP PUT isteği için bir işlem metotunu işaretlemek için kullanılır.
    – Parametreler:
    – `value` (veya `path`): İsteği işleyecek URL yolunu belirtir. String tipindedir.
    – `consumes`: İsteğin kabul edebileceği medya tiplerini belirtir. String array olarak verilir.
    – `produces`: Yanıtın üretebileceği medya tiplerini belirtir. String array olarak verilir.
  • @DeleteMapping: HTTP DELETE isteği için bir işlem metotunu işaretlemek için kullanılır.
    – Parametreler:
    – `value` (veya `path`): İsteği işleyecek URL yolunu belirtir. String tipindedir.
    – `produces`: Yanıtın üretebileceği medya tiplerini belirtir. String array olarak verilir.

5. Hibernate’in Önemi ve Kullanımı

Hibernate, Java uygulamalarında veritabanı işlemlerini kolaylaştıran popüler bir nesne ilişkisel eşleme (ORM) çerçevesidir. Hibernate, veritabanı tabloları ile Java sınıfları arasındaki ilişkiyi yönetir ve veritabanı işlemlerini nesne odaklı bir şekilde gerçekleştirmenizi sağlar. REST servislerinde Hibernate, veritabanı entegrasyonunu kolaylaştırır ve CRUD işlemlerini basitleştirir.

Hibernate’in önemi ve kullanımı aşağıdaki şekilde sıralanmıştır;

  • Nesne Tabanlı Veritabanı Etkileşimi: Hibernate, Java sınıflarını veritabanı tablolarıyla eşleştirmenizi sağlar. Bu şekilde, veritabanı işlemlerini daha kolay ve sade bir şekilde gerçekleştirilebilir.
  • ORM Kolaylığı: Hibernate, SQL sorgularını manuel olarak oluşturmak yerine nesne tabanlı sorgularla çalışmanıza olanak tanır. Bu sayede veritabanı işlemlerini daha hızlı ve daha az hata ile gerçekleştirilebilir.
  • Veritabanı Bağımsızlığı: Hibernate, farklı veritabanı sistemleriyle çalışabilme esnekliği sağlar. Aynı Hibernate kodunu kullanarak farklı veritabanı sistemlerine (Oracle, MySQL, PostgreSQL vb.) uyumlu uygulamalar geliştirilebilir.
    Spring Boot projelerinde Hibernate kullanmak için aşağıdaki adımları izlenir:

5.1. Pom.xml Dosyasına Ekleniş Biçimi:

Hibernate’ı Spring Boot projesine eklemek için Maven veya Gradle gibi proje yönetim araçlarını kullanılabilir.

5.2. Hibernate ile Veritabanı Yapılandırması:

Hibernate kullanarak veritabanına erişmek için, veritabanı bağlantı bilgilerini ve yapılandırmasını Spring Boot’ın application.properties (veya application.yml) dosyasında belirtmelidir. Örneğin, PostgreSQL veritabanı için bir örnek yapılandırma aşağıda bulunmaktadır.

# application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/mydatabase
spring.datasource.username=db_username
spring.datasource.password=db_password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

5.3. Hibernate Entity Sınıfı Oluşturma:

Hibernate kullanarak bir veritabanı tablosunu temsil eden bir Java sınıfı oluşturmanız gerekmektedir. Bu sınıfı @Entity annotation’ı ile işaretleyerek ve @Id, @GeneratedValue gibi Hibernate annotation’larını kullanarak anahtar sütunları ve diğer sütunları tanımlanmalıdır.

Bu şekilde Hibernate’i Spring Boot projesine ekleyebilir ve Hibernate ile veritabanı etkileşimini sağlayan sınıfları oluşturulabilir. Daha sonra bu sınıfları Rest servislerinizde kullanarak veritabanı işlemlerini gerçekleştirilebilir.

6. Lombok frameworkü:

Lombok, Java projelerinde kod tekrarını azaltmak ve daha okunabilir, sade ve bakımı kolay kodlar yazmayı sağlayan bir Java kütüphanesidir. Lombok, sınıflarda getter, setter, equals, hashCode, toString gibi yaygın kod parçalarını otomatik olarak üretir ve bu sayede geliştiricilerin bu kodları elle yazma ihtiyacını ortadan kaldırır.Lombok’ün sağladığı diğer anotasyonlar dan bazılarını aşağıda bulabilirsiniz.

1. @Getter/@Setter: Bu annotation’lar, sınıfın tüm alanları için getter ve setter metodlarını otomatik olarak oluşturur. Bu sayede sınıf içerisinde tekrarlayıcı getter/setter metotlarını elle yazmak zorunda kalmazsınız.

2. @NoArgsConstructor/@AllArgsConstructor: Bu annotation’lar, parametresiz bir yapıcı metot veya tüm alanları içeren bir yapıcı metot otomatik olarak oluşturur. Bu sayede sınıfın nesnelerini oluştururken tekrarlayıcı yapıcı metotları elle yazmak zorunda kalmazsınız.

3. @Data: Bu annotation, @Getter, @Setter, @ToString, @EqualsAndHashCode ve @RequiredArgsConstructor annotation’larını birleştirir. Sınıf için tüm bu tekrarlayıcı metotları otomatik olarak oluşturur.

Aşağıda Pom dosyasına nasıl eklenmesi gerektiği gösterilmiştir.

7. Postman Kullanımı

REST servislerini test etmek için Postman gibi bir araç kullanabilirsiniz. Postman, HTTP isteklerini kolayca oluşturmanıza ve göndermenize olanak tanır. Örneğin, UserController’da tanımlanan `/users` endpoint’ini test etmek için Postman’da bir GET veya POST isteği oluşturabilir ve sonucu incelenebilir.

Postman’da istek oluşturmak için aşağıdaki şekilde istek ayarlarını yapılandırılmalı:

HTTP metodu (GET, POST, PUT, DELETE) seçin ve URL’yi belirtin.
Headers (Başlıklar): İstek başlıklarını gerektiğinde ekleyin. Örneğin, “Content-Type” başlığı “application/json” olarak ayarlanabilir.
Body (Gövde): Eğer bir POST veya PUT isteği yapıyorsanız, veriyi body (gövde) bölümünde belirtin. Örneğin, JSON formatında bir veri göndermek için “raw” seçeneğini seçin ve JSON verisini girin.

8. Örnek Proje: Adres Bilgisi Çeken REST Servisi

Aşağıda, bir REST servisi örneği verilmiştir. Bu örnek, kullanıcının sorgusunda kullandığı adres bilgisini çeker ve bu adres bilgisini kullanarak tamamen ücretsiz bir platform olan OpenStreetMap API sine bağlanarak lokasyon verisini çekip bu veriyi müşteriye dönen bir servistir.

Pom XML:

<?xml version=”1.0″ encoding=”UTF-8″?>

<project xmlns=”http://maven.apache.org/POM/4.0.0″

         xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

         xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>

    <artifactId>my-project</artifactId>

    <version>1.0-SNAPSHOT</version>

    <properties>

        <java.version>1.8</java.version>

        <spring-boot.version>2.5.2</spring-boot.version>

        <lombok.version>1.18.20</lombok.version>

        <hibernate.version>5.4.32.Final</hibernate.version>

    </properties>

    <dependencies>

        <!– Spring Boot Starter Web –>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

            <version>${spring-boot.version}</version>

        </dependency>

        <!– Spring Boot Starter Data JPA –>

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-data-jpa</artifactId>

            <version>${spring-boot.version}</version>

        </dependency>

        <!– H2 Database –>

        <dependency>

            <groupId>com.h2database</groupId>

            <artifactId>h2</artifactId>

            <version>1.4.200</version>

        </dependency>

        <!– Lombok –>

        <dependency>

            <groupId>org.projectlombok</groupId>

            <artifactId>lombok</artifactId>

            <version>${lombok.version}</version>

            <scope>provided</scope>

        </dependency>

        <!– Hibernate Core –>

        <dependency>

            <groupId>org.hibernate</groupId>

            <artifactId>hibernate-core</artifactId>

            <version>${hibernate.version}</version>

        </dependency>

        <!– JSON Processing API –>

        <dependency>

            <groupId>javax.json</groupId>

            <artifactId>javax.json-api</artifactId>

            <version>1.1.4</version>

        </dependency>

        <!– Jersey Client –>

        <dependency>

            <groupId>org.glassfish.jersey.core</groupId>

            <artifactId>jersey-client</artifactId>

            <version>2.34</version>

        </dependency>

    </dependencies>

    <build>

        <plugins>

            <!– Maven Compiler Plugin –>

            <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-compiler-plugin</artifactId>

                <version>3.8.1</version>

                <configuration>

                    <source>${java.version}</source>

                    <target>${java.version}</target>

                </configuration>

            </plugin>

            <!– Spring Boot Maven Plugin –>

            <plugin>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-maven-plugin</artifactId>

                <version>${spring-boot.version}</version>

            </plugin>

        </plugins>

    </build>

</project>

Adres Entity Sınıfı:

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Data;

@Entity
@Data
public class Adres {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String adres;
private String haritaLink;
}

Adres Repository Sınıfı:

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AdresRepository extends JpaRepository<Adres, Long> {
Adres findByAdres(String adres);
}

Adres Servis Sınıfı:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.json.*;


@Service
public class AdresServis {
private final AdresRepository adresRepository;

@Autowired
public AdresServis(AdresRepository adresRepository) {
this.adresRepository = adresRepository;
}


public String getHaritaLink(String adres) {
Adres bulunanAdres = adresRepository.findByAdres(adres);
if (bulunanAdres != null) {
return bulunanAdres.getHaritaLink();
} else {
String haritaLink = getHaritaLinkFromAPI(adres);
Adres yeniAdres = new Adres();
yeniAdres.setAdres(adres);
yeniAdres.setHaritaLink(haritaLink);
adresRepository.save(yeniAdres);
return haritaLink;
}
}

private String getHaritaLinkFromAPI(String adres) {
String haritaLink = "";
try {
URIBuilder uriBuilder = new URIBuilder("https://nominatim.openstreetmap.org/search");
uriBuilder.addParameter("format", "json");
uriBuilder.addParameter("q", adres);


URI uri = uriBuilder.build();

HttpClient httpClient = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(uri);
BufferedReader reader = new BufferedReader(new InputStreamReader(httpClient.execute(request).getEntity().getContent()));

StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
JsonArray jsonArray = JsonParser.parseString(response.toString()).getAsJsonArray();

if (jsonArray.size() > 0) {
JsonObject firstResult = jsonArray.get(0).getAsJsonObject();
haritaLink = firstResult.get("url").getAsString();
}
} catch (Exception e) {
e.printStackTrace();
}

return haritaLink;
}
}

Adres Kontrolcü Sınıfı:

import org.springframework.beans.factory.annotation.Autowired;
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("/adresler")
public class AdresKontrolcu {
private final AdresServis adresServis;

@Autowired
public AdresKontrolcu(AdresServis adresServis) {
this.adresServis = adresServis;
}

@GetMapping
public String getAdresHaritaLink(@RequestParam("adres") String adres) {
String haritaLink = adresServis.getHaritaLink(adres);
return "Adres: " + adres + ", Harita Linki: " + haritaLink;
}
}

Postman Sorgusu:
– Request Method: GET
– URL: `http://localhost:8080/adresler?adres=Ankara`
Postman Çıktısı:
Adres: Ankara, Harita Linki: ‘“https://www.openstreetmap.org/?lat=39.9334&lon=32.8597&zoom=12&layers=M”’

Umarım yukarıda paylaştığım bilgiler sizlere yardımcı olmuştur.
Başarılar dilerim!