Merhaba,

 

Bu yazıda Java framework'ü olan Spring ile Rest API yapımından bahsedeceğim. Örnek proje temel CRUD işlemlerini içerecek. Not ekleme, listeleme, düzenleme ve silme işlemleri mevcut olacak.

 

İlk olarak start.spring.io sitesine girip şu ayarlarla bir Spring projesi oluşturuyorum:

 

Projeyi IDE üzerinde açarak paket yapısını oluşturuyorum:

 

Local ortamda MySQL ile spring-rest-api adında bir veritabanı oluşturdum. Ardından /src/main/resources/application.properties dosyasında veritabanı bağlantı bilgilerini tanımlıyorum:

spring.datasource.url=jdbc:mysql://localhost:3306/spring-rest-api
spring.datasource.username=root
spring.datasource.password=12345678

spring.jpa.hibernate.ddl-auto=update

spring.jpa.hibernate.ddl-auto=update ile modeller üzerindeki değişikliklerin otomatik olarak veritabanına aktarılmasını sağlamış olacağım.

 

Veritabanında notes adında bir tablom olacak. Bu tabloda id, title, description, created_at ve updated_at sütunları bulunacak. Bunu modellemek için model paketi altında Note.java dosyası oluşturuyorum:

package com.yusufborucu.springrestapi.model;

import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.time.LocalDateTime;

@Entity
@Table(name = "notes")
public class Note {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "Başlık boş olamaz.")
    @Size(max = 20, message = "Başlık 20 karakterden fazla olamaz.")
    private String title;

    @NotBlank(message = "Açıklama boş olamaz.")
    private String description;

    @CreationTimestamp
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;

    @UpdateTimestamp
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;

    public Long getId() {
        return id;
    }

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

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public LocalDateTime getCreated_at() {
        return createdAt;
    }

    public void setCreated_at(LocalDateTime created_at) {
        this.createdAt = created_at;
    }

    public LocalDateTime getUpdated_at() {
        return updatedAt;
    }

    public void setUpdated_at(LocalDateTime updated_at) {
        this.updatedAt = updated_at;
    }

}
  • @Entity anotasyonu ile bu sınıfın bir veritabanı tablosunu modelleyeceğini belirttim.
  • @Table anotasyonundan faydalanarak tablo adının notes olmasını sağladım. Bunu kullanmasaydım tablo adı note olarak oluşacaktı.
  • @Id ve @GeneratedValue ile id sütununun primary key olacağını ve otomatik artarak devam edeceğini belirttim.
  • @NotBlank ve @Size ile validasyonlar ekledim.
  • @CreationTimestamp, @UpdateTimestamp ile created_at ve updated_at sütunlarının oluşturma ve güncelleme zamanlarını ifade edeceğini belirttim.
  • getter ve setter fonksiyonlarını tanımladım. Bunlar Spring Data JPA tarafından kullanılacak. Aslında burada Lombok kütüphanesini kullanıp bu tarz boilerplate kodları yazmadan anotasyonlar ile de işimizi halledebilirdik ancak ben bu seferlik böyle yapmayı tercih ettim. Lombok hakkında bilgi almak için buraya bakabilirsiniz.

 

Şimdi de veritabanı işlemlerinin yapılacağı repository katmanında NoteRepository.java dosyası oluşturuyorum:

package com.yusufborucu.springrestapi.repository;

import com.yusufborucu.springrestapi.model.Note;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface NoteRepository extends JpaRepository<Note, Long> {
}

NoteRepository bir interface olarak tanımlanıyor ve de JpaRepository'i extend ediyor. Bu tanımlama sayesinde ekstra bir kod yazmadan ihtiyacımız olan işlemleri kullanabileceğiz.

 

Controller ve repository katmanı arasında bilgi alışverişini sağlayacak olan service katmanında NoteService.java dosyası oluşturuyorum:

package com.yusufborucu.springrestapi.service;

import com.yusufborucu.springrestapi.model.Note;
import com.yusufborucu.springrestapi.repository.NoteRepository;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class NoteService {

    private final NoteRepository noteRepository;

    public NoteService(NoteRepository noteRepository) {
        this.noteRepository = noteRepository;
    }

    public Note addNote(Note note) {
        return noteRepository.save(note);
    }

    public List<Note> getNotes() {
        return noteRepository.findAll();
    }

    public Note getNote(Long id) {
        Optional<Note> note = noteRepository.findById(id);
        if (note.isPresent()) {
            return note.get();
        }
        throw new RuntimeException("Note is not found");
    }

    public Note editNote(Long id, Note newNote) {
        Note existNote = getNote(id);
        existNote.setTitle(newNote.getTitle());
        existNote.setDescription(newNote.getDescription());
        return noteRepository.save(existNote);
    }

    public void deleteNote(Long id) {
        noteRepository.deleteById(id);
    }

}

Az önce tanımladığımız repository'i burada kullanıyoruz ve save, findAll, findById, deleteById gibi fonksiyonlara doğrudan erişim sağlayabiliyoruz.

 

Son olarak da gelen istekleri karşılayacak olan controller katmanında NoteController.java dosyası oluşturuyorum:

package com.yusufborucu.springrestapi.controller;

import com.yusufborucu.springrestapi.model.Note;
import com.yusufborucu.springrestapi.service.NoteService;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class NoteController {

    private final NoteService noteService;

    public NoteController(NoteService noteService) {
        this.noteService = noteService;
    }

    @GetMapping("/notes")
    public List<Note> getNotes() {
        return noteService.getNotes();
    }

    @PostMapping("/notes")
    public Note addNote(@RequestBody Note note) {
        return noteService.addNote(note);
    }
    
    @GetMapping("/notes/{id}")
    public Note getNote(@PathVariable Long id) {
        return noteService.getNote(id);
    }

    @PutMapping("/notes/{id}")
    public Note editNote(@PathVariable Long id, @RequestBody Note note) {
        return noteService.editNote(id, note);
    }

    @DeleteMapping("/notes/{id}")
    public void deleteNote(@PathVariable Long id) {
        noteService.deleteNote(id);
    }

}

@GetMapping, @PostMapping vs. anotasyonlar ile GET, POST vs. istekleri karşılıyorum. Servisi kullanarak gerekli cevapları dönüyorum. @RequestBody ile note verisini alıyorum, @PathVariable ile url'deki id'ye ulaşıyorum.

 

Projeyi ayağa kaldırıyorum ve Postman üzerinden testlerimi gerçekleştiriyorum:

 

Not ekle:

 

Notları listele:

 

Notu getir:

 

Not düzenle:

 

Not sil:

 

Projenin kaynak kodlarına buradan ulaşabilirsiniz.

 

Umarım yararlı olmuştur.

 

İyi çalışmalar.