Jak napisać prosty REST API w Spring Boot dla początkujących

Marek Radoszewski Marek Radoszewski
Backend i Frontend
18.03.2026 12 min
Jak napisać prosty REST API w Spring Boot dla początkujących

Wprowadzenie do prostego REST API w Spring Boot

Zastanawiasz się, jak napisać prosty REST API w Spring Boot dla początkujących backend 2026 i od czego w ogóle zacząć? Umiejętność budowania API to dziś fundament pracy programisty backend, niezależnie od tego, czy tworzysz aplikacje mobilne, SPA, czy systemy mikrousług. Spring Boot pozwala wejść w ten świat szybko i bez bolesnej konfiguracji.

W tym artykule krok po kroku zbudujesz swoje pierwsze REST API w Spring Boot. Skupisz się na praktyce, tworząc działający projekt, który obsługuje proste operacje CRUD. Przejdziesz przez przygotowanie środowiska, wygenerowanie szkieletu aplikacji, implementację endpointów oraz testowanie API.

Wyobraź sobie, że Twoja aplikacja to restauracja, a dane to potrawy. REST API jest menu i kelnerem, który pośredniczy między „klientem” (frontem, aplikacją mobilną) a „kuchnią” (serwerem). Dzięki jasno zdefiniowanym zasadom komunikacji różne systemy mogą wymieniać dane w przewidywalny i uporządkowany sposób.

Spring Boot to „król” ekosystemu Javy, który realizuje zasadę konwencja ponad konfiguracją. Oznacza to, że zamiast walczyć z XML-ami i rozbudowanym setupem, skupiasz się na logice biznesowej. Framework jest masowo wykorzystywany w firmach produktowych i software house’ach, a jego znajomość pozostanie bardzo cenna także w 2026 roku.

Programista tworzący prosty REST API w Spring Boot dla początkujących backend 2026 w nowoczesnym IDE na laptopie

Dlaczego warto w 2026 umieć pisać REST API w Spring Boot?

REST API to dziś standard komunikacji pomiędzy serwerem a klientem. Gdy aplikacja mobilna pobiera listę produktów, panel administracyjny zapisuje nowe dane, a mikroserwisy wymieniają informacje – za kulisami zazwyczaj działa właśnie REST. To uniwersalny sposób na expose’owanie danych i funkcjonalności do świata zewnętrznego.

Spring Boot natomiast zapewnia gotową infrastrukturę, dzięki której wdrożenie REST API sprowadza się w dużej mierze do pisania klas kontrolerów, serwisów i modeli. Nie musisz ręcznie konfigurować serwera aplikacyjnego ani zależności – projekt startuje w kilka minut.

Znajomość Spring Boot i REST API przekłada się bezpośrednio na Twoją atrakcyjność na rynku pracy. Wiele rekrutacji backendowych w Javie zakłada zadania właśnie z implementacji prostych endpointów, obsługi CRUD oraz integracji z bazą danych. Ucząc się tego dziś, inwestujesz w kompetencje, które będą aktualne również w 2026 roku i później.

Przygotowanie środowiska developerskiego

Zanim napiszesz pierwszy endpoint, potrzebujesz podstawowego środowiska do pracy ze Spring Boot i Javą. Skonfigurujesz kilka kluczowych narzędzi, które będą fundamentem Twojej dalszej nauki programowania backend.

Niezbędne komponenty: JDK, Maven/Gradle, IDE

Do pracy z Spring Boot potrzebujesz przede wszystkim:

  • Java Development Kit (JDK) – zalecana jest aktualna stabilna wersja, np. Java 17 lub nowsza. JDK dostarcza kompilator, runtime i narzędzia konieczne do uruchamiania aplikacji.
  • Narzędzie do budowania projektu – najpopularniejsze to Maven i Gradle. W tym przykładzie użyjesz Mavena, który jest standardem w wielu projektach komercyjnych.
  • IDE do Javy – wygodne środowisko pracy znacznie przyspiesza naukę. Masz kilka sprawdzonych opcji:
  • IntelliJ IDEA Community Edition – darmowe, bardzo popularne i dobrze zoptymalizowane pod Javę,
  • Visual Studio Code z rozszerzeniami do Javy – lekkie i elastyczne,
  • Eclipse – klasyk w świecie Javy, również darmowy.

Po zainstalowaniu JDK i Mavena/Gradle upewnij się, że są dostępne w zmiennej środowiskowej PATH. Następnie zainstaluj wybrane IDE, w którym otworzysz generowany za chwilę projekt Spring Boot.

Sprawdzenie instalacji i gotowości środowiska

Po instalacji możesz szybko zweryfikować konfigurację z poziomu terminala lub wiersza poleceń:

  • Sprawdzenie wersji Javy: bash java -version
  • Sprawdzenie wersji Mavena (jeśli korzystasz z Mavena lokalnie): bash mvn -version

Jeśli obie komendy zwracają poprawne wersje, środowisko jest gotowe. Teraz możesz przejść do wygenerowania szkieletu aplikacji Spring Boot, korzystając z Spring Initializr.

Tworzenie projektu Spring Boot w Spring Initializr

Aby nie zaczynać od pustego katalogu i ręcznej konfiguracji, wykorzystasz Spring Initializr, który generuje gotowy do uruchomienia projekt. Dzięki temu szybko zobaczysz działające REST API w praktyce.

Konfiguracja projektu w Spring Initializr

  1. Otwórz przeglądarkę i przejdź do narzędzia Spring Initializr.
  2. W sekcji ustawień projektu skonfiguruj podstawowe elementy:
  3. Project: Maven Project
  4. Language: Java
  5. Spring Boot: najnowsza stabilna wersja, np. 3.x.x
  6. Wypełnij metadane projektu:
  7. Group: pl.radoszewski (lub np. com.example)
  8. Artifact: my-first-api
  9. Name: my-first-api
  10. Description: Proste REST API dla portalu Radoszewski.pl
  11. Package Name: pl.radoszewski.myfirstapi
  12. Packaging: Jar
  13. Java: wersja zgodna z zainstalowanym JDK (np. 17)

Następnie przejdź do sekcji zależności, gdzie wybierzesz biblioteki potrzebne do stworzenia prostego REST API.

Dodanie zależności i import projektu do IDE

W polu zależności kliknij Add Dependencies i wyszukaj:

  • Spring Web – to kluczowy starter, który dodaje obsługę REST, kontrolerów, wbudowanego serwera i niezbędnych komponentów sieciowych.

Po dodaniu zależności kliknij Generate, aby pobrać wygenerowany projekt jako archiwum .zip. Rozpakuj go w wybranym katalogu i otwórz w IDE:

  • W IntelliJ IDEA użyj File -> Open i wskaż folder projektu,
  • IDE zaimportuje projekt jako projekt Maven, pobierze zależności i zbuduje go.

Po zakończonym imporcie w strukturze katalogów znajdziesz m.in. klasę MyFirstApiApplication.java – to główny punkt startowy aplikacji Spring Boot.

Pierwszy endpoint REST w Spring Boot

Masz już gotowy szkielet aplikacji, więc czas dodać pierwszy, bardzo prosty endpoint REST. Dzięki adnotacjom Spring Boot konfiguracja sprowadza się do kilku linijek kodu w kontrolerze.

Tworzenie kontrolera HelloController

Przejdź do katalogu src/main/java/pl/radoszewski/myfirstapi i utwórz nową klasę HelloController.java:

package pl.radoszewski.myfirstapi;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String helloWorld() {
        return "Cześć, świecie z Radoszewski.pl!";
    }
}

W tej klasie dzieje się kilka ważnych rzeczy:

  • @RestController informuje Springa, że klasa udostępnia endpointy REST i domyślnie zwraca dane bezpośrednio w odpowiedzi HTTP.
  • @GetMapping("/hello") mapuje żądania HTTP GET pod adresem /hello na metodę helloWorld.
  • Metoda helloWorld() zwraca prosty tekst, który zostanie przesłany jako odpowiedź do klienta.

To najprostszy możliwy przykład REST API w Spring Boot, idealny na początek nauki backendu w Javie.

Uruchamianie aplikacji i pierwszy test

Znajdź klasę MyFirstApiApplication.java i uruchom jej metodę main z poziomu IDE. W konsoli zobaczysz logi startowe Spring Boot oraz informację o uruchomieniu wbudowanego serwera na porcie 8080.

Po starcie aplikacji możesz przetestować endpoint na kilka sposobów:

  • W przeglądarce wpisz adres: text http://localhost:8080/hello
  • Powinieneś zobaczyć tekst: text Cześć, świecie z Radoszewski.pl!

To pierwszy dowód, że konfiguracja Spring Boot działa, a Ty właśnie uruchomiłeś swoje pierwsze REST API. W kolejnych krokach rozbudujesz projekt o model danych, warstwę serwisu i pełne operacje CRUD.

Dodanie modelu danych Task i warstwy serwisu

Sam tekst „Cześć, świecie” to za mało, by poczuć prawdziwą moc Spring Boot. Zbudujesz więc proste API do zarządzania zadaniami (tasks). Na razie dane będą przechowywane w pamięci, bez bazy danych, żebyś mógł skupić się na podstawach API.

Schemat działania prostego REST API w Spring Boot zarządzającego zadaniami Task z operacjami CRUD dla początkujących backend 2026

Definicja modelu Task

W pakiecie pl.radoszewski.myfirstapi utwórz nowy pakiet model, a w nim klasę Task.java:

package pl.radoszewski.myfirstapi.model;

public class Task {
    private Long id;
    private String title;
    private String description;
    private boolean completed;

    // Konstruktor
    public Task(Long id, String title, String description, boolean completed) {
        this.id = id;
        this.title = title;
        this.description = description;
        this.completed = completed;
    }

    // Pusty konstruktor (potrzebny Springowi do deserializacji)
    public Task() {
    }

    // Gettery i Settery
    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 boolean isCompleted() {
        return completed;
    }

    public void setCompleted(boolean completed) {
        this.completed = completed;
    }
}

Ta klasa reprezentuje pojedyncze zadanie w Twoim systemie. Zawiera:

  • id – identyfikator zadania,
  • title – krótki tytuł,
  • description – opis,
  • completed – informację, czy zadanie jest zakończone.

Pusty konstruktor jest niezbędny, aby Spring (i biblioteka Jackson) mógł deserializować obiekty z JSON-a przychodzącego w żądaniu HTTP.

Implementacja serwisu TaskService

Kolejnym krokiem jest warstwa serwisu, która będzie zarządzała listą zadań. W pakiecie pl.radoszewski.myfirstapi utwórz podpakiet service i klasę TaskService.java:

package pl.radoszewski.myfirstapi.service;

import pl.radoszewski.myfirstapi.model.Task;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;

@Service
public class TaskService {
    private final List<Task> tasks = new ArrayList<>();
    private final AtomicLong nextId = new AtomicLong(1); // Do generowania unikalnych ID

    public TaskService() {
        // Dodajemy kilka początkowych zadań
        tasks.add(new Task(nextId.getAndIncrement(), "Napisz pierwszy wpis na bloga", "Stwórz kompleksowy artykuł o Spring Boot", false));
        tasks.add(new Task(nextId.getAndIncrement(), "Zoptymalizuj wpis pod SEO", "Dodaj słowa kluczowe i nagłówki", false));
        tasks.add(new Task(nextId.getAndIncrement(), "Zrób kawę", "Mocną i aromatyczną!", true));
    }

    public List<Task> getAllTasks() {
        return new ArrayList<>(tasks); // Zwracamy kopię, aby lista wewnętrzna była bezpieczna
    }

    public Optional<Task> getTaskById(Long id) {
        return tasks.stream()
                .filter(task -> task.getId().equals(id))
                .findFirst();
    }

    public Task addTask(Task task) {
        task.setId(nextId.getAndIncrement());
        tasks.add(task);
        return task;
    }

    public Optional<Task> updateTask(Long id, Task updatedTask) {
        return getTaskById(id).map(existingTask -> {
            existingTask.setTitle(updatedTask.getTitle());
            existingTask.setDescription(updatedTask.getDescription());
            existingTask.setCompleted(updatedTask.isCompleted());
            return existingTask;
        });
    }

    public boolean deleteTask(Long id) {
        return tasks.removeIf(task -> task.getId().equals(id));
    }
}

Najważniejsze elementy tego serwisu:

  • @Service – adnotacja, która oznacza komponent logiki biznesowej zarządzany przez Springa.
  • List<Task> tasks – prosta „baza danych” w pamięci, przechowująca listę zadań.
  • AtomicLong nextId – generator unikalnych identyfikatorów dla nowych zadań.
  • Metody CRUD:
  • getAllTasks() – zwraca wszystkie zadania,
  • getTaskById() – pobiera zadanie po ID,
  • addTask() – dodaje nowe zadanie,
  • updateTask() – aktualizuje istniejące zadanie,
  • deleteTask() – usuwa zadanie po ID.

Taka architektura z wyraźnym podziałem na model i serwis jest dobrym wprowadzeniem do późniejszego korzystania z baz danych i dodatkowych warstw (np. repozytoriów).

Kontroler TaskController – pełne REST API CRUD

Masz już model danych oraz logikę biznesową. Teraz trzeba wystawić je na zewnątrz w formie REST API. Zrobisz to, tworząc kontroler TaskController, który będzie obsługiwał żądania HTTP i korzystał z serwisu.

Konfiguracja kontrolera i mapowanie endpointów

W pakiecie pl.radoszewski.myfirstapi utwórz podpakiet controller, a w nim klasę TaskController.java. Opcjonalnie możesz usunąć wcześniejszy HelloController, aby projekt był bardziej uporządkowany:

package pl.radoszewski.myfirstapi.controller;

import pl.radoszewski.myfirstapi.model.Task;
import pl.radoszewski.myfirstapi.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/tasks") // Wszystkie endpointy w tym kontrolerze będą poprzedzone /api/tasks
public class TaskController {

    private final TaskService taskService;

    @Autowired // Spring sam wstrzyknie instancję TaskService
    public TaskController(TaskService taskService) {
        this.taskService = taskService;
    }

    @GetMapping // GET /api/tasks
    public List<Task> getAllTasks() {
        return taskService.getAllTasks();
    }

    @GetMapping("/{id}") // GET /api/tasks/{id}
    public ResponseEntity<Task> getTaskById(@PathVariable Long id) {
        return taskService.getTaskById(id)
                .map(task -> new ResponseEntity<>(task, HttpStatus.OK))
                .orElseGet(() -> new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    @PostMapping // POST /api/tasks
    public ResponseEntity<Task> addTask(@RequestBody Task task) {
        Task newTask = taskService.addTask(task);
        return new ResponseEntity<>(newTask, HttpStatus.CREATED);
    }

    @PutMapping("/{id}") // PUT /api/tasks/{id}
    public ResponseEntity<Task> updateTask(@PathVariable Long id, @RequestBody Task task) {
        return taskService.updateTask(id, task)
                .map(updatedTask -> new ResponseEntity<>(updatedTask, HttpStatus.OK))
                .orElseGet(() -> new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    @DeleteMapping("/{id}") // DELETE /api/tasks/{id}
    public ResponseEntity<Void> deleteTask(@PathVariable Long id) {
        if (taskService.deleteTask(id)) {
            return new ResponseEntity<>(HttpStatus.NO_CONTENT); // Brak treści, ale sukces
        }
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }
}

W tym kontrolerze warto zwrócić uwagę na kilka elementów:

  • @RequestMapping("/api/tasks") – ustawia wspólny prefiks URL-a dla wszystkich endpointów kontrolera.
  • Konstruktor z adnotacją @Autowired – Spring automatycznie wstrzykuje instancję TaskService, realizując Dependency Injection.
  • Metody opatrzone @GetMapping, @PostMapping, @PutMapping, @DeleteMapping – każda odpowiada konkretnej operacji HTTP na zasobie Task.

Dzięki temu powstało kompletne REST API dla zadań, które umożliwia tworzenie, odczytywanie, aktualizację oraz usuwanie danych.

Adnotacje, ResponseEntity i statusy HTTP

Każda metoda operująca na pojedynczym zadaniu zwraca ResponseEntity, co pozwala kontrolować zarówno treść odpowiedzi, jak i kod statusu HTTP. To ważne elementy profesjonalnego API:

  • @PathVariable – odczytuje fragment ścieżki URL jako parametr metody (np. id w /api/tasks/{id}).
  • @RequestBody – informuje Springa, że parametrem jest JSON z ciała żądania, który należy zdeserializować do obiektu Task.
  • ResponseEntity – umożliwia ustawianie kodów:
  • HttpStatus.OK (200) – gdy operacja się powiodła,
  • HttpStatus.CREATED (201) – gdy utworzono nowy zasób,
  • HttpStatus.NO_CONTENT (204) – gdy usunięto zasób bez treści odpowiedzi,
  • HttpStatus.NOT_FOUND (404) – gdy nie znaleziono zasobu o podanym ID.

Tak zaprojektowane API jest czytelne, spójne i zgodne z dobrymi praktykami REST, co ma duże znaczenie w realnych projektach backendowych.

Testowanie REST API z użyciem curl i Postmana

Po zaimplementowaniu API czas sprawdzić, czy wszystko działa zgodnie z oczekiwaniami. Możesz użyć zarówno prostych narzędzi terminalowych, jak i wygodnego interfejsu graficznego.

Szybkie testy w terminalu za pomocą curl

Upewnij się, że aplikacja jest uruchomiona na porcie 8080, a następnie wykonaj poniższe komendy:

  • Pobranie wszystkich zadań (GET): bash curl http://localhost:8080/api/tasks
  • Pobranie zadania po ID (GET): bash curl http://localhost:8080/api/tasks/1
  • Dodanie nowego zadania (POST): bash curl -X POST -H "Content-Type: application/json" -d '{"title":"Nauka Spring Boota", "description":"Kontynuuj naukę i twórz nowe projekty", "completed":false}' http://localhost:8080/api/tasks
  • Aktualizacja zadania (PUT): bash curl -X PUT -H "Content-Type: application/json" -d '{"title":"Nauka Spring Boota - zakończona", "description":"Spring Boot opanowany!", "completed":true}' http://localhost:8080/api/tasks/4
  • Usunięcie zadania (DELETE): bash curl -X DELETE http://localhost:8080/api/tasks/4

Po każdym żądaniu zobaczysz w odpowiedzi JSON z zadaniem lub odpowiedni kod HTTP. To prosty sposób na walidację logiki CRUD bez wychodzenia z terminala.

Testowanie API w Postmanie lub Insomnia

Jeśli wolisz narzędzie z GUI, idealnym wyborem będzie Postman lub Insomnia. Pozwalają one wygodnie wysyłać żądania HTTP i analizować odpowiedzi:

  1. Utwórz nowe żądanie i ustaw metodę HTTP (GET, POST, PUT, DELETE).
  2. W polu adresu wpisz URL, np.:
  3. http://localhost:8080/api/tasks
  4. http://localhost:8080/api/tasks/1
  5. Dla metod POST i PUT:
  6. Przejdź do zakładki Body,
  7. Wybierz raw oraz format JSON,
  8. Wpisz treść żądania, np.: json { "title": "Nowe zadanie", "description": "Test z Postmana", "completed": false }
  9. Kliknij Send i sprawdź odpowiedź oraz status HTTP.

W ten sposób możesz szybko zweryfikować wszystkie endpointy, sprawdzając poprawność danych i zachowanie API w różnych scenariuszach.

Co dalej po pierwszym REST API w Spring Boot?

Stworzyłeś już działające proste REST API w Spring Boot dla początkujących backend 2026, obsługujące pełen zestaw operacji CRUD na zasobie Task. To solidny fundament, ale świat backendu oferuje o wiele więcej możliwości rozwoju.

Możesz kontynuować naukę w kilku naturalnych kierunkach:

  • Integracja z bazą danych – zamiast listy w pamięci użyj Spring Data JPA i bazy H2, PostgreSQL lub MySQL. Pozwoli to utrwalać dane między restartami aplikacji.
  • Obsługa błędów – wprowadź globalny mechanizm obsługi wyjątków i zwracaj ustrukturyzowane komunikaty błędów w formacie JSON.
  • Walidacja danych – korzystając z adnotacji typu @NotBlank czy @Size, możesz zadbać o poprawność danych wejściowych.
  • Bezpieczeństwo z Spring Security – dodaj uwierzytelnianie i autoryzację, aby chronić swoje endpointy.
  • Testy jednostkowe i integracyjne – naucz się pisać testy dla serwisów i kontrolerów, aby utrzymać wysoką jakość kodu.
  • Dokumentacja API – użyj Swagger/OpenAPI do generowania interaktywnej dokumentacji, z której skorzystają inni programiści.

Nie zatrzymuj się na pierwszym działającym projekcie. Eksperymentuj, dodawaj kolejne funkcjonalności i buduj coraz bardziej zaawansowane usługi. Z takim fundamentem wejście w świat mikrousług i profesjonalnego backendu w Javie stanie się znacznie prostsze.

Marek Radoszewski

Autor

Marek Radoszewski

Freelance developer i tech blogger od 7 lat. Pracował przy projektach dla klientów z Polski, UK i USA. Na blogu pisze o praktycznych aspektach programowania, narzędziach i tym, jak skutecznie rozwijać karierę jako niezależny programista.

Wróć do kategorii Backend i Frontend