# Spring i Spring Boot wyjasnione prosto - od czego zaczac nauke w Javie

Kazdy kurs Javy prędzej czy pozniej trafia na Springa - problem w tym, ze niewiele materialow tlumaczy prosto skad sie wzial i dlaczego Spring Boot to nie to samo co Spring Framework. Ten tekst to nadrabia.

![Działająca aplikacja Spring Boot w przeglądarce: katalog książek z kartami, kategoriami i cenami, wyrenderowany na serwerze przez Thymeleaf](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_hero_katalog.png)

Nasza aplikacja demonstracyjna w akcji. To katalog książek wyrenderowany po stronie serwera przez Spring Boot i szablony Thymeleaf. Dane pochodzą z komponentu BookstoreService. Kliknij zrzut, aby powiększyć.

Jeśli uczysz się programowania w Javie, prędzej czy później natrafisz na dwa słowa, które padają niemal w każdej ofercie pracy: **Spring** i **Spring Boot**. Brzmią podobnie, często występują razem, a mimo to nie znaczą tego samego. W tym przewodniku wyjaśnimy od zera, **co to jest Spring Framework**, **co to jest Spring Boot** i czym te dwie rzeczy się różnią. Nie na diagramach z internetu, tylko na prawdziwej aplikacji, którą specjalnie na potrzeby tego artykułu zbudowaliśmy i uruchomiliśmy: mała księgarnia z REST-owym adresem (interfejsem programistycznym zwracającym dane) i strona HTML renderowana na serwerze. Wszystkie zrzuty pochodzą z tej działającej aplikacji.

**W pigułce:** **Spring Framework** to szkielet (framework) do budowy aplikacji w Javie - daje mechanizmy takie jak wstrzykiwanie zależności, obsługa żądań sieciowych czy transakcje. **Spring Boot** to nadbudowa nad Spring Framework, która te mechanizmy sama konfiguruje i pozwala uruchomić aplikację jednym poleceniem. Krótko: Framework daje klocki, a Boot składa je za Ciebie i od razu uruchamia.

Z tego artykułu dowiesz się:

- [co to jest Spring Framework i z jakich modułów się składa](https://jsystems.pl/blog/show_post/co-to-jest-spring-framework-i-spring-boot/#spring-framework),
- [czym jest wstrzykiwanie zależności (dependency injection) i po co komu kontener IoC](https://jsystems.pl/blog/show_post/co-to-jest-spring-framework-i-spring-boot/#di),
- [co to jest Spring Boot i czym różni się od samego Spring Framework](https://jsystems.pl/blog/show_post/co-to-jest-spring-framework-i-spring-boot/#spring-boot),
- [czym są startery i na czym polega auto-konfiguracja](https://jsystems.pl/blog/show_post/co-to-jest-spring-framework-i-spring-boot/#startery),
- [jak wygenerować projekt na Spring Initializr i uruchomić go jednym poleceniem](https://jsystems.pl/blog/show_post/co-to-jest-spring-framework-i-spring-boot/#initializr),
- [jak Spring obsługuje żądanie WWW (Spring MVC) i jak zwraca dane jako JSON](https://jsystems.pl/blog/show_post/co-to-jest-spring-framework-i-spring-boot/#mvc),
- [jak renderować strony HTML na serwerze za pomocą Thymeleaf](https://jsystems.pl/blog/show_post/co-to-jest-spring-framework-i-spring-boot/#thymeleaf),
- [do czego służy Actuator i jak sprawdzić kondycję aplikacji](https://jsystems.pl/blog/show_post/co-to-jest-spring-framework-i-spring-boot/#actuator),
- [jak wygląda cały ekosystem Spring](https://jsystems.pl/blog/show_post/co-to-jest-spring-framework-i-spring-boot/#ekosystem).

**Wolisz od razu zajrzeć w działający kod?** Cały projekt tej aplikacji (Spring Boot, Maven, Java 21) jest publicznie na GitHubie. Sklonuj go i uruchom u siebie jednym poleceniem, żeby przejść ten przewodnik krok po kroku na własnym komputerze - wszystkie zrzuty w artykule pochodzą dokładnie z tego projektu:

Kopiuj

```
git clone https://github.com/konwertyta/spring-boot-bookstore-demo.git
cd spring-boot-bookstore-demo
mvn spring-boot:run
```

Pobranie i uruchomienie aplikacji demonstracyjnej. Po starcie otwórz w przeglądarce http://localhost:8085 (strona HTML) oraz http://localhost:8085/api/books (te same dane jako JSON).

## Co to jest Spring Framework?

**Spring Framework to szkielet do budowy aplikacji w języku Java, który bierze na siebie techniczną czarną robotę, żebyś Ty mógł skupić się na logice biznesowej.** Słowo szkielet (z angielskiego framework) oznacza gotowy fundament aplikacji: zestaw mechanizmów i zasad, w które wpinasz swój kod, zamiast pisać wszystko od podstaw. Spring zajmuje się między innymi tworzeniem obiektów i łączeniem ich ze sobą, obsługą żądań przychodzących z sieci, dostępem do bazy danych czy transakcjami (czyli pilnowaniem, żeby zestaw operacji na bazie wykonał się w całości albo wcale).

Kluczowe jest to, że Spring jest **modularny**. Nie jest jednym wielkim blokiem, który musisz wziąć w całości. To zestaw współpracujących modułów, z których bierzesz tylko te, których potrzebujesz. Sercem całości jest tak zwany kontener (o nim za chwilę), a wokół niego narastają moduły do sieci, danych czy testów.

![Infografika modułów Spring Framework: rdzeń z kontenerem IoC, Beans i Context oraz SpEL, a wokół moduły Web/MVC, Data Access, AOP i Test](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_modules.png)

Spring Framework to modularny zestaw. W środku jest rdzeń z kontenerem, który tworzy obiekty i łączy je ze sobą, a wokół niego moduły do obsługi WWW, dostępu do danych, programowania aspektowego i testów.

### Krótka historia Springa

Spring powstał jako odpowiedź na przekombinowanie wczesnych technologii Javy korporacyjnej. Jego korzenie sięgają kodu, który [Rod Johnson](https://spring.io/projects/spring-framework) opublikował w 2002 roku, a pierwsza wersja frameworka ukazała się w 2004. Chodziło o jedno: żeby budowa aplikacji była prosta, a zwykły obiekt Javy (tak zwany POJO, czyli Plain Old Java Object - obiekt bez narzuconych zależności od frameworka) nie musiał dziedziczyć po dziwnych klasach ani wypełniać stert konfiguracji. Przez ponad dwie dekady Spring urósł do najpopularniejszego szkieletu w świecie Javy po stronie serwera.

## Wstrzykiwanie zależności, czyli serce Springa

Żeby zrozumieć Springa, trzeba zrozumieć jeden pomysł: **wstrzykiwanie zależności** (z angielskiego dependency injection). Brzmi poważnie, a chodzi o coś prostego. Wyobraź sobie, że kontroler obsługujący żądania potrzebuje serwisu z logiką. Bez Springa musiałbyś sam napisać `new BookstoreService()` w każdym miejscu, w którym ten serwis jest potrzebny, i sam pilnować, ile takich obiektów powstaje. Ze Springiem jest odwrotnie: to **Spring tworzy obiekt i sam podaje go tam, gdzie jest potrzebny**. Ty tylko mówisz, czego potrzebujesz.

To odwrócenie odpowiedzialności nazywa się **odwróceniem sterowania** (z angielskiego Inversion of Control, w skrócie IoC). Nie Ty tworzysz i spinasz obiekty, tylko robi to za Ciebie **kontener** Springa - to znaczy ta część frameworka, która zarządza cyklem życia obiektów. Same obiekty tworzone i zarządzane przez kontener nazywamy **ziarnami** (z angielskiego beans). Zobaczmy to na animacji z naszej księgarni:

Jak taka solidna znajomość fundamentów przekłada się na utrzymanie się w zawodzie mimo AI, piszemy w artykule o [doświadczonym programiście w czasach sztucznej inteligencji](https://jsystems.pl/blog/show_post/jak-przetrwac-w-branzy-it-senior-w-czasach-ai).

![Animacja wstrzykiwania zależności w Springu: kontener IoC tworzy ziarno BookstoreService i wstrzykuje je do dwóch kontrolerów](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_di.gif)

Wstrzykiwanie zależności krok po kroku. Kontener Springa tworzy jeden obiekt BookstoreService i wstrzykuje go do kontrolera REST oraz do kontrolera widoku. Ten sam obiekt jest współdzielony w całej aplikacji.

W naszej aplikacji serwis to zwykła klasa oznaczona adnotacją (czyli specjalnym znacznikiem) `@Service`. Adnotacja mówi Springowi: to jest komponent, zajmij się nim. Dzięki temu Spring sam utworzy jego obiekt i będzie go pilnował.

Kopiuj

```
@Service
public class BookstoreService {

    private final List<Book> catalog = List.of(
        new Book(1L, "Thinking in Java", "Bruce Eckel", 2006, new BigDecimal("149.00"), "Java"),
        new Book(2L, "Spring in Action", "Craig Walls", 2022, new BigDecimal("189.00"), "Spring"));

    public List<Book> findAll() {
        return catalog;
    }

    public List<Book> findByCategory(String category) {
        return catalog.stream()
                .filter(b -> b.category().equalsIgnoreCase(category))
                .toList();
    }
}
```

Kopiuj

BookstoreService: zwykła klasa z logiką, oznaczona jako komponent Springa adnotacją @Service.

A teraz najważniejsze. Kontroler nie tworzy serwisu ręcznie. On tylko **przyjmuje go w konstruktorze**, a Spring sam podstawia gotowy obiekt. To właśnie jest wstrzykiwanie zależności przez konstruktor - dziś zalecany sposób w Springu:

Chcesz opanować te mechanizmy w praktyce, budując aplikacje pod okiem praktyka? [Szkolenie Spring Framework](https://jsystems.pl/szkolenia-java;tworzenie_aplikacji_w_javie_z_uzyciem_spring_framework.szczegoly?utm_source=blog&utm_medium=article&utm_campaign=post464&utm_content=link_tworzenie_aplikacji_w_javie_z_uzyciem_spring_framework) ma terminy gwarantowane.

Kopiuj

```
@RestController
@RequestMapping("/api/books")
public class BookRestController {

    private final BookstoreService service;

    // Nie piszemy 'new BookstoreService()'. Spring sam podaje gotowy
    // obiekt serwisu przez konstruktor - to jest wstrzykiwanie zależności.
    public BookRestController(BookstoreService service) {
        this.service = service;
    }

    @GetMapping
    public List<Book> list(@RequestParam(required = false) String category) {
        return category == null ? service.findAll() : service.findByCategory(category);
    }
}
```

Kopiuj

Kontroler REST przyjmuje BookstoreService w konstruktorze. Nie ma tu ani jednego 'new' - gotowy obiekt podaje Spring.

**Dlaczego to takie ważne?** Bo dzięki temu klasy nie są ze sobą na sztywno zrośnięte. Serwis można podmienić (na przykład na wersję testową) bez dotykania kontrolera, a cały kod łatwiej się testuje i utrzymuje. To jest realna wartość Springa, a nie sama adnotacja.

## Co to jest Spring Boot i czym różni się od Spring Framework?

Sam Spring Framework jest potężny, ale na starcie bywa wymagający: trzeba samodzielnie poskładać konfigurację, wybrać i podpiąć serwer, dobrać pasujące do siebie wersje bibliotek. W 2014 roku pojawił się **Spring Boot**, który tę barierę zdejmuje. **Spring Boot to nadbudowa nad Spring Framework, która sama dobiera rozsądną konfigurację, ma wbudowany serwer WWW i pozwala uruchomić aplikację jednym poleceniem.**

Kluczowe słowo to **nadbudowa**, a nie zamiennik. Spring Boot nie zastępuje Spring Framework - on na nim stoi i go wykorzystuje. Kiedy piszesz aplikację w Spring Boot, cały czas korzystasz z mechanizmów Spring Framework (choćby z opisanego wyżej wstrzykiwania zależności). Boot jedynie oszczędza Ci ręcznej roboty konfiguracyjnej.

![Infografika porównująca Spring Framework i Spring Boot: po lewej zestaw mechanizmów do samodzielnego złożenia, po prawej te same klocki już złożone i gotowe do uruchomienia](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_vs_boot.png)

Spring Framework a Spring Boot to nie konkurenci. Framework daje mechanizmy (klocki), a Boot sprawia, że te mechanizmy ruszają od ręki: sam konfiguruje, ma wbudowany serwer i uruchamia się jednym poleceniem.

## Startery: koniec z ręcznym dobieraniem bibliotek

Pierwsza wygoda Spring Boot to **startery**. Starter to jedna zależność, która pod spodem wciąga cały zestaw dobranych i przetestowanych razem bibliotek. Zamiast ręcznie zbierać kilkanaście bibliotek i modlić się, żeby ich wersje do siebie pasowały, dopisujesz jeden wiersz.

![Infografika startera Spring Boot: jedna zależność spring-boot-starter-web rozwija się w Spring MVC, Tomcat, Jackson i Validation](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_starter.png)

Idea startera. Jedna zależność spring-boot-starter-web wciąga komplet potrzebny do aplikacji WWW: Spring MVC, wbudowany serwer Tomcat, bibliotekę Jackson do JSON-a i mechanizm walidacji danych.

Tak wygląda fragment pliku `pom.xml` (pliku, w którym narzędzie Maven opisuje zależności projektu) z naszej księgarni. Trzy startery dają komplet: aplikację WWW, szablony HTML i podgląd stanu aplikacji. Zwróć uwagę, że przy zależnościach nie ma numerów wersji - dobiera je za nas nadrzędny projekt startowy Spring Boot:

Kopiuj

```
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.4.0</version>
</parent>

<dependencies>
    <!-- Web + REST + wbudowany serwer Tomcat -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Szablony HTML renderowane na serwerze -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <!-- Podgląd stanu aplikacji: health, metryki -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>
```

Kopiuj

Fragment pom.xml: trzy startery Spring Boot. Wersje bibliotek dobiera nadrzędny spring-boot-starter-parent, więc nie musimy ich podawać ręcznie.

## Spring Initializr: generujemy szkielet projektu

Skąd wziąć gotowy projekt z odpowiednim `pom.xml`? Nie trzeba go pisać ręcznie. Służy do tego [Spring Initializr](https://start.spring.io/) (start.spring.io) - internetowy generator startowych projektów Spring Boot. Wybierasz narzędzie do budowania (my użyliśmy Mavena), język, wersję Javy, wpisujesz nazwę projektu i zaznaczasz zależności. Generator pakuje gotowy projekt do pobrania.

![Zrzut ekranu Spring Initializr z wybranym Mavenem, Java 21, metadanymi projektu bookstore i czterema dodanymi zależnościami po prawej stronie](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_initializr.png)

Spring Initializr z ustawieniami naszego projektu: Maven, Java 21, nazwa pl.jsystems / bookstore oraz zależności Spring Web, Thymeleaf, Spring Boot Actuator i Validation. Kliknięcie Generate pobiera gotowy szkielet.

Po lewej stronie ustawiasz typ projektu i dane, po prawej dokładasz zależności (to właśnie startery). Przycisk Generate pobiera archiwum z kompletnym, gotowym do uruchomienia szkieletem. To standardowy pierwszy krok każdego projektu w Spring Boot.

## Pierwsza aplikacja: budujemy i uruchamiamy

W wygenerowanym projekcie jest jedna klasa startowa. To od niej wszystko się zaczyna. Adnotacja `@SpringBootApplication` mówi Springowi: to jest aplikacja Spring Boot, włącz swoje mechanizmy i poszukaj moich komponentów. Metoda `main` uruchamia cały framework.

Kopiuj

```
@SpringBootApplication
public class BookstoreApplication {

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

Kopiuj

Cała klasa startowa aplikacji Spring Boot. Adnotacja @SpringBootApplication włącza mechanizmy Springa, a SpringApplication.run podnosi aplikację.

Projekt budujemy Mavenem. Polecenie `mvn clean package` kompiluje kod i pakuje wszystko do jednego pliku JAR - razem z bibliotekami i wbudowanym serwerem w środku. To właśnie dzięki temu aplikację da się później uruchomić jednym poleceniem, bez instalowania osobnego serwera.

![Zrzut terminala z budowaniem projektu Spring Boot przez Maven: kompilacja pięciu plików źródłowych, pakowanie do JAR i komunikat BUILD SUCCESS](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_term_build.png)

Budowanie aplikacji poleceniem mvn clean package. Maven kompiluje kod i pakuje go do jednego pliku JAR. Na końcu widać BUILD SUCCESS.

Teraz uruchamiamy aplikację poleceniem `java -jar`. I tu pojawia się znak rozpoznawczy Spring Boot - charakterystyczny napis Spring w konsoli, a pod nim log startu. Widać w nim, że wbudowany serwer Tomcat wstał na porcie 8085, że nasz komponent zgłosił sześć książek w katalogu, i że cała aplikacja wstała w niecałe sześć sekund:

![Zrzut terminala ze startem aplikacji Spring Boot: baner Spring w wersji 3.4.0, uruchomienie wbudowanego serwera Tomcat na porcie 8085 i komunikat Started BookstoreApplication](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_term_banner.png)

Uruchomienie aplikacji poleceniem java -jar. Charakterystyczny baner Spring Boot, a pod nim log startu: wbudowany Tomcat na porcie 8085, komunikat naszego serwisu o sześciu książkach i informacja, że aplikacja wstała.

## Auto-konfiguracja: magia, która magią nie jest

Skąd Spring Boot wiedział, że ma uruchomić serwer Tomcat na porcie i przygotować obsługę żądań WWW, skoro nigdzie tego nie konfigurowaliśmy? To zasługa **auto-konfiguracji**. Działa ona według prostej zasady: **Boot patrzy, jakie biblioteki masz na ścieżce klas** (to znaczy wśród zależności projektu) i na tej podstawie sam włącza rozsądne, domyślne ustawienia.

![Animacja auto-konfiguracji Spring Boot: od startera na ścieżce klas, przez sprawdzenie warunku, po gotową aplikację z ustawionym serwerem i komponentami](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_autoconfig.gif)

Auto-konfiguracja krok po kroku. Starter wciąga biblioteki, Spring Boot sprawdza, co jest na ścieżce klas, i gdy widzi Spring MVC oraz Tomcat, sam konfiguruje działającą aplikację WWW.

To nie jest magia - to zwykłe sprawdzanie warunków. Spring Boot potrafi pokazać, co i dlaczego skonfigurował. Wystarczy uruchomić aplikację z opcją `--debug`, a w konsoli pojawi się raport oceny warunków. Widać w nim, że obsługa żądań i serwer Tomcat zostały włączone, bo odpowiednie klasy są na ścieżce klas (sekcja Positive matches). I odwrotnie: konfiguracje pod inne serwery, jak Jetty, Netty czy Undertow, zostały pominięte, bo tych bibliotek u nas nie ma (sekcja Negative matches):

![Zrzut terminala z raportem oceny warunków Spring Boot: sekcja dopasowań pozytywnych z Tomcatem i obsługą żądań oraz sekcja dopasowań negatywnych z pominiętymi serwerami Jetty, Netty i Undertow](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_term_autoconfig.png)

Raport auto-konfiguracji z opcji --debug. Positive matches: obsługa żądań i serwer Tomcat włączone, bo ich klasy są na ścieżce klas. Negative matches: Jetty, Netty i Undertow pominięte, bo tych bibliotek nie ma.

## REST w praktyce: dane jako JSON

Aplikacja działa, więc sprawdźmy, co potrafi. Pokazany wcześniej kontroler był oznaczony adnotacją `@RestController`. To znaczy, że zwraca dane, a nie stronę HTML. Adnotacja `@GetMapping` podpina metodę pod adres, a Spring sam zamienia zwróconą listę obiektów na **JSON** - lekki, tekstowy format wymiany danych, który rozumie niemal każdy język programowania i każda przeglądarka.

Odpytajmy nasz adres `/api/books` narzędziem curl. Za pierwszym razem prosimy o cały katalog, a za drugim dokładamy parametr `?category=Spring`. Ten parametr trafia do metody przez adnotację `@RequestParam` i zawęża wynik tylko do książek z kategorii Spring - bez pisania ani linijki dodatkowego kodu obsługi adresu:

![Zrzut terminala z dwoma wywołaniami curl do REST-owego adresu książek: pełny katalog w formacie JSON oraz wynik przefiltrowany po kategorii Spring](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_term_rest.png)

Odpytanie adresu /api/books narzędziem curl. Pierwsze wywołanie zwraca cały katalog jako JSON, drugie z parametrem category=Spring zawęża wynik do dwóch książek. Dane składa komponent BookstoreService.

## Jak Spring obsługuje żądanie (Spring MVC)

Skąd Spring wie, że żądanie spod adresu `/api/books` ma trafić akurat do naszej metody? Odpowiada za to **Spring MVC** - moduł do obsługi żądań sieciowych. Sercem jest w nim jeden komponent o nazwie **DispatcherServlet**, czyli centralny dyspozytor. Każde żądanie przychodzące do aplikacji przechodzi najpierw przez niego, a on kieruje je do właściwej metody kontrolera. Prześledźmy tę drogę:

![Animacja przepływu żądania w Spring MVC: przeglądarka, DispatcherServlet, kontroler i serwis, a następnie powrotna droga odpowiedzi JSON](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_mvc.gif)

Droga żądania w Spring MVC. Żądanie z przeglądarki trafia do centralnego dyspozytora DispatcherServlet, ten kieruje je do właściwego kontrolera, kontroler prosi serwis o dane, a odpowiedź w formacie JSON wraca do przeglądarki.

Ten sam DispatcherServlet, który widzieliśmy w logu startu, obsługuje wszystkie żądania - i te zwracające dane (JSON), i te zwracające strony HTML. Różnica jest tylko w tym, co kontroler postanowi oddać.

## Strona HTML po stronie serwera (Thymeleaf)

Katalog książek, który widziałeś na samej górze artykułu, to nie JSON, tylko gotowa strona HTML. Zbudował ją **Thymeleaf** - silnik szablonów, który po stronie serwera wstawia dane do szablonu HTML i oddaje przeglądarce gotową stronę. Tym razem kontroler jest oznaczony zwykłym `@Controller` (a nie `@RestController`) i zwraca nazwę szablonu:

Kopiuj

```
@Controller
public class ViewController {

    private final BookstoreService service;

    public ViewController(BookstoreService service) {
        this.service = service;
    }

    @GetMapping("/")
    public String catalog(Model model) {
        model.addAttribute("books", service.findAll());
        return "catalog";   // nazwa szablonu: templates/catalog.html
    }
}
```

Kopiuj

Kontroler widoku. Dokłada dane do modelu i zwraca nazwę szablonu 'catalog'. Resztę, czyli złożenie strony, robi Thymeleaf.

W samym szablonie używamy atrybutów Thymeleaf. Atrybut `th:each` przechodzi w pętli po liście książek i powiela kartę, a `th:text` wstawia w wyznaczone miejsca konkretne wartości. To dlatego jedna karta w szablonie zamienia się w sześć kart na gotowej stronie:

Kopiuj

```
<article class="card" th:each="b : ${books}">
    <span class="badge" th:text="${b.category}">Kategoria</span>
    <h2               th:text="${b.title}">Tytuł książki</h2>
    <p  class="author" th:text="${b.author}">Autor</p>
    <span th:text="${b.price} + ' zł'">cena</span>
</article>
```

Kopiuj

Fragment szablonu Thymeleaf. Atrybut th:each powiela kartę dla każdej książki, a th:text wstawia tytuł, autora, kategorię i cenę.

## Actuator: gotowość produkcyjna

Ostatni element, który dołożyliśmy, to **Actuator**. To moduł Spring Boot, który wystawia gotowe adresy do podglądu i monitorowania stanu działającej aplikacji: jej kondycji, metryk czy listy komponentów. W praktyce to on odpowiada za produkcyjną dojrzałość aplikacji Spring Boot. Włączamy go i wybieramy, co ma pokazywać, w pliku `application.properties`:

Kopiuj

```
spring.application.name=bookstore
server.port=8085

# Actuator - wystawiamy punkty monitorujące stan aplikacji
management.endpoints.web.exposure.include=health,info,metrics,beans
management.endpoint.health.show-details=always
```

Kopiuj

Fragment application.properties. Ustawiamy port, włączamy wybrane adresy Actuatora i prosimy o pełne szczegóły kondycji aplikacji.

Najczęściej odpytywany adres to `/actuator/health`. Zwraca on kondycję aplikacji i jej składowych. W naszym przypadku wszystko jest na zielono - status UP, a pod nim stan miejsca na dysku, testu ping i certyfikatów:

![Zrzut terminala z odpowiedzią adresu health Spring Boot Actuator: status UP oraz szczegóły składowych diskSpace, ping i ssl w formacie JSON](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_term_actuator.png)

Adres /actuator/health z modułu Actuator. Zwraca kondycję aplikacji: status UP oraz stan składowych - miejsca na dysku, testu ping i certyfikatów SSL.

## Ekosystem Spring to nie jeden projekt

Spring to dziś cała rodzina projektów zbudowanych na wspólnym fundamencie. Poza samym rdzeniem i Spring Boot warto znać kilka nazw, które prędzej czy później spotkasz:

![Infografika ekosystemu Spring z sześcioma projektami: Spring Boot, Spring Data, Spring Security, Spring Cloud, Spring Batch i Spring WebFlux](https://jsystems.pl/new_page_resources/images/SPRING_KURS/spring_ecosystem.png)

Ekosystem Spring. Poza Spring Boot to między innymi Spring Data (dostęp do baz), Spring Security (logowanie i uprawnienia), Spring Cloud (aplikacje rozproszone), Spring Batch (przetwarzanie wsadowe) i Spring WebFlux (programowanie reaktywne).

Szczególnie warto zapamiętać **Spring Cloud**. To zestaw narzędzi do budowy aplikacji rozproszonych, czyli takich, które zamiast jednego dużego programu składają się z wielu małych współpracujących usług (mikroserwisów). To właśnie Spring Boot najczęściej stoi za pojedynczym mikroserwisem. Jeśli chcesz zrozumieć, kiedy w ogóle warto dzielić aplikację na mniejsze części, zajrzyj do naszego osobnego przewodnika [monolit kontra mikroserwisy](https://jsystems.pl/blog/show_post/Monolit_vs_Mikroserwisy_kiedy_warto_dzielic_aplikacje_przewodnik_architekta_2026/) - dobrze uzupełnia to, co pokazaliśmy tutaj.

Czy w erze generowania kodu przez AI warto w ogóle uczyć się takich frameworków, rozkładamy na dane w artykule o tym, [czy AI zastąpi programistów](https://jsystems.pl/blog/show_post/czy-ai-zastapi-programistow).

## Podsumowanie

**Spring Framework** to modularny szkielet do budowy aplikacji w Javie, którego sercem jest wstrzykiwanie zależności: to kontener tworzy obiekty i sam podaje je tam, gdzie są potrzebne. **Spring Boot** to nadbudowa nad tym szkieletem, która dzięki starterom i auto-konfiguracji sama dobiera ustawienia, ma wbudowany serwer i pozwala uruchomić aplikację jednym poleceniem. W naszej małej księgarni zobaczyliśmy oba w akcji: od wygenerowania projektu, przez budowę i start z charakterystycznym banerem, po REST zwracający JSON, stronę HTML z Thymeleaf i podgląd kondycji przez Actuator.

Najlepszy sposób nauki to praktyka: wygeneruj własny projekt na Spring Initializr, dodaj kontroler z jedną metodą i uruchom aplikację, dokładnie tak jak pokazaliśmy. A jeśli chcesz przejść przez to z trenerem praktykiem i poukładać wiedzę o Springu w dobrej kolejności - od wstrzykiwania zależności, przez Spring MVC, po dostęp do danych i transakcje - mamy dla Ciebie szkolenie.

Chcesz opanować Springa od praktyka?

Szkolenie **Spring Framework - szkolenie kompleksowe** przeprowadzi Cię przez cały framework na żywym kodzie: wstrzykiwanie zależności, konfigurację, Spring MVC, dostęp do danych i transakcje. Szkolenie ma **terminy gwarantowane**, czyli odbędzie się na pewno.

[![Baner szkolenia Spring Framework - szkolenie kompleksowe w JSystems, z terminem gwarantowanym](https://jsystems.pl/new_page_resources/images/other/spring_fb.jpg)](https://jsystems.pl/szkolenia-java;tworzenie_aplikacji_w_javie_z_uzyciem_spring_framework.szczegoly?utm_source=blog&utm_medium=article&utm_campaign=post__POSTID__&utm_content=banner_spring_framework)

[Szkolenie Spring Framework - szkolenie kompleksowe -->](https://jsystems.pl/szkolenia-java;tworzenie_aplikacji_w_javie_z_uzyciem_spring_framework.szczegoly?utm_source=blog&utm_medium=article&utm_campaign=post__POSTID__&utm_content=link_spring_framework)

To szkolenie może być [dofinansowane dla Ciebie z KFS lub BUR](https://jsystems.pl/dofinansowanie?utm_source=blog&utm_medium=article&utm_campaign=post464&utm_content=dofinansowanie).

★★★★★Średnia ocena naszych szkoleń w Google: **5/5**

✕![Powiększony zrzut ekranu z artykułu o Spring Framework i Spring Boot]()

## Powiązane artykuły

- ›[Doświadczony programista w czasach AI](https://jsystems.pl/blog/show_post/jak-przetrwac-w-branzy-it-senior-w-czasach-ai)
- ›[Markdown - ściąga i wszystkie elementy składni (cheatsheet)](https://jsystems.pl/blog/show_post/markdown-od-podstaw-kompletny-przewodnik-skladnia)
- ›[Monolit vs Mikroserwisy - kiedy warto dzielić aplikację, a kiedy lepiej tego nie](https://jsystems.pl/blog/show_post/Monolit_vs_Mikroserwisy_kiedy_warto_dzielic_aplikacje_przewodnik_architekta_2026)
- ›[Linux w codziennej pracy programisty](https://jsystems.pl/blog/show_post/Linux_w_codziennej_pracy_programisty_dlaczego_warto_znac_terminal_Bash)
- ›[Czy AI zastąpi programistów? Oddzielamy dane od marketingu](https://jsystems.pl/blog/show_post/czy-ai-zastapi-programistow)
- ›[Jak zostać programistą w czasach AI](https://jsystems.pl/blog/show_post/jak-zostac-programista-w-czasach-ai)
