Spring Boot Basic – Tag 1 von 10
Von Elyndra Valen, Senior Entwicklerin bei Java Fleet Systems Consulting


Spring Boot REST

📍 Deine Position im Kurs

TagThemaStatus
1Erste REST API👉 DU BIST HIER!
2Spring Container & DI + CRUDNoch nicht freigeschaltet
3@Controller & Thymeleaf BasicsNoch nicht freigeschaltet
4Thymeleaf Forms & MVC-PatternNoch nicht freigeschaltet
5Konfiguration & LoggingNoch nicht freigeschaltet
6DI & AOP im DetailNoch nicht freigeschaltet
7Scopes in SpringNoch nicht freigeschaltet
8WebSocketsNoch nicht freigeschaltet
9JAX-RS in Spring BootNoch nicht freigeschaltet
10Integration & AbschlussNoch nicht freigeschaltet

📋 Voraussetzungen

Du brauchst:

  • ✅ Java 21 (oder mindestens Java 17) installiert
  • ✅ NetBeans IDE (oder IntelliJ/Eclipse/VS Code)
  • ✅ Maven (kommt meist mit der IDE)
  • ✅ Optional: curl oder Postman zum Testen

Neu bei Spring Boot? Perfekt – hier startest du von Null! 🚀


⚡ Was du heute baust/lernst:

Deine erste Spring Boot REST Anwendung mit einem REST Service. Erst „Hello World“, dann eine Person-API mit echten Daten. Am Ende hast du eine funktionierende REST API, die JSON zurückgibt – ohne komplizierte Konfiguration. Kein Schnickschnack – einfach Code der läuft.


🎯 Dein Lernpfad heute:

Du arbeitest heute in mehreren aufbauenden Schwierigkeitsstufen. Arbeite in deinem eigenen Tempo durch die Schritte:

🟢 Grundlagen (Schritte 1-6)

Was du lernst:

  • Spring Boot Projekt mit Spring Initializr erstellen
  • Die Projektstruktur verstehen (pom.xml, Package-Struktur)
  • Deinen ersten @RestController schreiben
  • HTTP GET Requests beantworten
  • Java-Objekte automatisch zu JSON konvertieren lassen
  • Eine Person-API mit manuell erstellten Daten bauen

Ziel: Eine funktionierende REST API, die „Hello World“ und eine Liste von Personen als JSON zurückgibt.

🟡 Professional (Schritte 7-8)

Was du lernst:

  • Datafaker-Library für realistische Testdaten einsetzen
  • 100 Personen mit deutschen Namen generieren
  • PathVariable für ID-basierte Abfragen nutzen
  • ResponseEntity für saubere HTTP Status-Codes (200, 404)
  • Best Practice: RequestMapping richtig einsetzen

Ziel: Production-Ready API mit realistischen Daten und professioneller Struktur.

🔵 Bonus: Enterprise Features (Schritt 9)

Was du baust/lernst:

  • Paginierung implementieren (page & size Parameter)
  • Such-Funktionalität nach Namen
  • RequestParams richtig einsetzen
  • Stream API für Filter-Operationen

Ziel: Enterprise-Level Features, die du in echten Projekten brauchst.

💡 Tipp: Die Grundlagen (Schritte 1-6) sind essenziell für alle weiteren Tage. Professional (Schritt 7-8) ist sehr empfehlenswert, da realistische Daten das Lernen erleichtern. Die Bonus-Features kannst du je nach Interesse und Zeit angehen – sie zeigen dir, was mit Spring Boot alles möglich ist.


💻 Los geht’s!

🟢 GRUNDLAGEN

Schritt 1: Projekt erstellen mit Spring Initializr

Wir nutzen NetBeans mit dem Spring Boot Plugin und erstellen unser Projekt mit dem Spring Initializr.

In NetBeans:

  1. File → New Project
  2. Java with Maven → Spring Boot Initializr
  3. Oder direkt im Browser: https://start.spring.io

Projekt-Konfiguration:

Project: Maven
Language: Java
Spring Boot: 3.4.5
Group: com.example
Artifact: helloworldapi
Name: HelloWorldAPI
Package name: com.example.helloworldapi
Packaging: Jar
Java: 21

Dependencies auswählen:

  • ✅ Spring Web
  • ✅ Spring Boot DevTools (optional, aber hilfreich!)

Klick auf „Generate“ – Projekt wird als ZIP heruntergeladen.

In NetBeans öffnen:

  • File → Open Project
  • ZIP entpacken und Ordner auswählen
  • NetBeans lädt automatisch die Maven Dependencies

Schritt 2: Die Projektstruktur verstehen

Spring Boot hat eine klare Struktur – lass uns reinschauen:

helloworldapi/
├── pom.xml                          ← Maven Dependencies
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/helloworldapi/
│   │   │       └── HelloWorldApiApplication.java  ← Main-Klasse
│   │   └── resources/
│   │       ├── application.properties             ← Konfiguration
│   │       ├── static/                           ← CSS, JS, Bilder
│   │       └── templates/                        ← HTML Templates
│   └── test/
│       └── java/
└── target/                          ← Compiled Classes (nach Build)

Die wichtigsten Dateien:

1. pom.xml – Deine Dependencies

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 
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.5</version>
        <relativePath/>
    </parent>
    
    <groupId>com.example</groupId>
    <artifactId>helloworldapi</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>HelloWorldAPI</name>
    
    <properties>
        <java.version>21</java.version>
    </properties>
    
    <dependencies>
        <!-- Spring Web - für REST APIs -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <!-- DevTools - Auto-Reload beim Entwickeln -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        
        <!-- Testing -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Was passiert hier?

  • spring-boot-starter-parent: Spring Boot Basis-Konfiguration – verwaltet Versionen aller Dependencies für dich
  • spring-boot-starter-web: Bringt alles für REST APIs mit (Tomcat, Spring MVC, Jackson)
  • spring-boot-devtools: Lädt deine App automatisch neu wenn du Code änderst
  • spring-boot-maven-plugin: Erlaubt mvn spring-boot:run

2. HelloWorldApiApplication.java – Deine Main-Klasse

java

package com.example.helloworldapi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HelloWorldApiApplication {

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

Was macht @SpringBootApplication?

Das ist 3 Annotations in einer:

  1. @Configuration – Diese Klasse kann Beans definieren
  2. @EnableAutoConfiguration – Spring Boot konfiguriert automatisch (z.B. Tomcat starten)
  3. @ComponentScan – Scannt nach @Component, @Service, @Controller in diesem Package

Einfach gesagt: Das ist der Startpunkt deiner App.


Schritt 3: Erste REST API – „Hello World“

Jetzt bauen wir unseren ersten REST Controller!

Erstelle: src/main/java/com/example/helloworldapi/controller/HelloController.java

java

package com.example.helloworldapi.controller;

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

@RestController
public class HelloController {
    
    @GetMapping("/hello")
    public String hello() {
        return "Hello World from Spring Boot!";
    }
}

Lass uns das Zeile für Zeile durchgehen:

@RestController

  • Sagt Spring: „Das ist ein REST Controller“
  • Kombiniert @Controller + @ResponseBody
  • Bedeutet: Alle Methoden geben direkt Daten zurück (kein HTML-Template)

@GetMapping("/hello")

  • Diese Methode reagiert auf HTTP GET Requests
  • URL: http://localhost:8080/hello
  • Alternativen: @PostMapping, @PutMapping, @DeleteMapping

public String hello()

  • Gibt einfach einen String zurück
  • Spring konvertiert automatisch zu HTTP Response
  • Content-Type: text/plain

Schritt 4: Starten & Testen

In NetBeans:

  • Rechtsklick auf Projekt → Run
  • Oder im Terminal: mvn spring-boot:run

Was passiert beim Start?

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.4.5)

2025-10-23T10:23:45.123  INFO 12345 --- [main] c.e.h.HelloWorldApiApplication
  : Starting HelloWorldApiApplication using Java 21
2025-10-23T10:23:47.456  INFO 12345 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer
  : Tomcat started on port(s): 8080 (http)
2025-10-23T10:23:47.789  INFO 12345 --- [main] c.e.h.HelloWorldApiApplication
  : Started HelloWorldApiApplication in 2.666 seconds

Spring Boot hat automatisch:

  • ✅ Tomcat Server gestartet (Port 8080)
  • ✅ Deinen Controller gefunden
  • ✅ Die Route /hello registriert

Teste es:

Im Browser:

http://localhost:8080/hello

Mit curl:

bash

curl http://localhost:8080/hello

Ergebnis:

Hello World from Spring Boot!

🎉 Glückwunsch! Deine erste REST API läuft!


Schritt 5: Upgrade zu JSON – Person API

„Hello World“ ist nett, aber langweilig. Lass uns echte Daten zurückgeben!

5.1 Person Model erstellen

Erstelle: src/main/java/com/example/helloworldapi/model/Person.java

java

package com.example.helloworldapi.model;

import java.util.Objects;

public class Person {
    
    private Long id;
    private String firstname;
    private String lastname;
    private String email;
    
    // Default-Konstruktor - Jackson braucht ihn für JSON → Java Konvertierung
    public Person() {
    }
    
    public Person(Long id, String firstname, String lastname, String email) {
        this.id = id;
        this.firstname = firstname;
        this.lastname = lastname;
        this.email = email;
    }
    
    // Getter und Setter
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getFirstname() { return firstname; }
    public void setFirstname(String firstname) { this.firstname = firstname; }
    
    public String getLastname() { return lastname; }
    public void setLastname(String lastname) { this.lastname = lastname; }
    
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    // Best Practice: toString, equals, hashCode
    @Override
    public String toString() {
        return "Person{id=" + id + ", firstname='" + firstname + 
               "', lastname='" + lastname + "', email='" + email + "'}";
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(id, person.id);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

Warum Getter/Setter?

  • Jackson (JSON Library) braucht sie, um Java → JSON zu konvertieren
  • Alternative später: Lombok oder Java Records (macht Getter/Setter automatisch)

Warum Default-Konstruktor?

  • Jackson braucht ihn, um JSON → Java zu konvertieren
  • Ohne Default-Konstruktor: Error beim Deserialisieren!

Warum toString, equals, hashCode?

  • toString() → Bessere Debugging-Ausgabe in Logs
  • equals() + hashCode() → Korrekte Vergleiche (z.B. in Collections)
  • Das ist Java-Best-Practice – gewöhn dir das von Anfang an an!

5.2 PersonController erstellen

Erstelle: src/main/java/com/example/helloworldapi/controller/PersonController.java

java

package com.example.helloworldapi.controller;

import com.example.helloworldapi.model.Person;
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;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/api/persons")
public class PersonController {
    
    private List<Person> persons = new ArrayList<>();
    
    public PersonController() {
        // Erstelle 3 Test-Personen
        persons.add(new Person(1L, "Anna", "Müller", "anna.mueller@example.com"));
        persons.add(new Person(2L, "Max", "Schmidt", "max.schmidt@example.com"));
        persons.add(new Person(3L, "Lisa", "Weber", "lisa.weber@example.com"));
    }
    
    @GetMapping
    public List<Person> getAllPersons() {
        return persons;
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<Person> getPersonById(@PathVariable Long id) {
        return persons.stream()
                .filter(p -> p.getId().equals(id))
                .findFirst()
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }
}

Lass uns das durchgehen:

@RequestMapping("/api/persons")

  • Basis-URL für ALLE Methoden in dieser Klasse
  • Alle Endpoints beginnen mit /api/persons

@GetMapping (ohne Parameter)

  • URL: http://localhost:8080/api/persons
  • Gibt alle Personen zurück

@GetMapping("/{id}")

  • URL: http://localhost:8080/api/persons/1
  • {id} ist ein Platzhalter

@PathVariable Long id

  • Spring extrahiert die {id} aus der URL
  • Konvertiert automatisch zu Long
  • Übergibt sie an die Methode

ResponseEntity – Saubere HTTP-Antworten

Statt einfach null zurückzugeben wenn eine Person nicht existiert, nutzen wir ResponseEntity. Das gibt uns Kontrolle über den HTTP Status-Code:

  • ResponseEntity.ok(person) → HTTP 200 + Person als JSON
  • ResponseEntity.notFound().build() → HTTP 404 (ohne Body)

Warum ist das besser als null?

  • Der Client bekommt einen klaren 404 Status-Code
  • REST-Clients können den Status-Code auswerten
  • null als JSON-Response ist kein guter API-Standard

persons.stream().filter(...)

  • Java Stream API – filtert die Liste nach ID
  • findFirst() gibt das erste Match als Optional
  • .map(ResponseEntity::ok) → Wenn gefunden: 200 OK
  • .orElse(ResponseEntity.notFound().build()) → Wenn nicht: 404

Schritt 6: Testen der Person API

Starte die App neu:

bash

mvn spring-boot:run

Alle Personen:

bash

curl http://localhost:8080/api/persons

Ergebnis:

json

[
  {
    "id": 1,
    "firstname": "Anna",
    "lastname": "Müller",
    "email": "anna.mueller@example.com"
  },
  {
    "id": 2,
    "firstname": "Max",
    "lastname": "Schmidt",
    "email": "max.schmidt@example.com"
  },
  {
    "id": 3,
    "firstname": "Lisa",
    "lastname": "Weber",
    "email": "lisa.weber@example.com"
  }
]

🎉 Spring Boot hat automatisch Java Objekte → JSON konvertiert!

Das macht Jackson (JSON Library) – ist automatisch dabei bei spring-boot-starter-web.

Eine Person nach ID:

bash

curl http://localhost:8080/api/persons/2

Ergebnis:

json

{
  "id": 2,
  "firstname": "Max",
  "lastname": "Schmidt",
  "email": "max.schmidt@example.com"
}

Was wenn ID nicht existiert?

bash

curl -v http://localhost:8080/api/persons/999

Ergebnis:

< HTTP/1.1 404 Not Found

Sauberer HTTP 404! Der Client weiß sofort: „Diese Ressource existiert nicht.“ Kein kryptisches null – sondern ein klarer Status-Code.


🟡 PROFESSIONAL

Schritt 7: Datafaker für realistische Daten

Drei Personen sind langweilig. Lass uns 100 realistische Personen generieren!

Wir nutzen Datafaker – eine Library die fake aber realistische Daten erzeugt.

7.1 Datafaker zu pom.xml hinzufügen:

xml

<dependency>
    <groupId>net.datafaker</groupId>
    <artifactId>datafaker</artifactId>
    <version>2.5.4</version>
</dependency>

In NetBeans:

  • Rechtsklick auf Projekt → Build with Dependencies
  • Oder Maven lädt automatisch beim nächsten Start

7.2 PersonController erweitern:

java

package com.example.helloworldapi.controller;

import com.example.helloworldapi.model.Person;
import net.datafaker.Faker;
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;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

@RestController
@RequestMapping("/api/persons")
public class PersonController {
    
    private final List<Person> persons = new ArrayList<>();
    
    public PersonController() {
        // Datafaker mit deutschem Locale
        Faker faker = new Faker(new Locale("de"));
        
        // 100 Personen generieren
        for (long i = 1; i <= 100; i++) {
            Person person = new Person(
                i,
                faker.name().firstName(),
                faker.name().lastName(),
                faker.internet().emailAddress()
            );
            persons.add(person);
        }
    }
    
    @GetMapping
    public List<Person> getAllPersons() {
        return persons;
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<Person> getPersonById(@PathVariable Long id) {
        return persons.stream()
                .filter(p -> p.getId().equals(id))
                .findFirst()
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }
}

Was macht Datafaker?

  • Faker faker = new Faker(new Locale("de")) – Deutsche Namen!
  • faker.name().firstName() – Generiert z.B. „Sebastian“, „Julia“
  • faker.name().lastName() – Generiert z.B. „Müller“, „Schmidt“
  • faker.internet().emailAddress() – Generiert z.B. „max.weber@example.com

Was hat sich geändert gegenüber vorher?

  • private final List<Person>final macht klar: Die Referenz ändert sich nicht (Best Practice)
  • ResponseEntity statt null bei getPersonById → Saubere HTTP-Antworten

Starte neu und teste:

bash

curl http://localhost:8080/api/persons

Ergebnis: 100 Personen mit realistischen deutschen Namen! 🇩🇪


Schritt 8: Best Practice – Code-Organisation

Momentan haben wir alles im Constructor. Das ist OK für kleine Demos, aber nicht professional.

Best Practice Tipp (Preview für Tag 2):

  • Daten-Management gehört in einen Service
  • Controller sollten nur HTTP-Requests handhaben
  • Morgen lernst du den Spring Container und Dependency Injection

Für Tag 1 ist unsere aktuelle Struktur völlig in Ordnung – du lernst die saubere Architektur morgen! 🎯


🔵 BONUS: ENTERPRISE FEATURES

Schritt 9: Paginierung und Suche

Du bist schnell? Hier sind Features die du in echten Enterprise-Projekten brauchst:

9.1 Paginierung – Nicht alle 100 auf einmal:

java

// GET /api/persons?page=0&size=10
@GetMapping
public List<Person> getAllPersons(
    @RequestParam(defaultValue = "0") int page,
    @RequestParam(defaultValue = "10") int size
) {
    int start = page * size;
    int end = Math.min(start + size, persons.size());
    
    if (start >= persons.size()) {
        return new ArrayList<>();
    }
    
    return persons.subList(start, end);
}

Was macht @RequestParam?

  • Liest Query-Parameter aus der URL
  • defaultValue = "0" – Wenn kein Parameter, nimm 0
  • Spring konvertiert automatisch String → int

Test:

bash

curl "http://localhost:8080/api/persons?page=0&size=5"  # Erste 5
curl "http://localhost:8080/api/persons?page=1&size=5"  # Nächste 5
curl "http://localhost:8080/api/persons?page=9&size=10" # Letzte 10

9.2 Suche nach Namen:

java

// GET /api/persons/search?name=Max
@GetMapping("/search")
public List<Person> searchByName(@RequestParam String name) {
    return persons.stream()
            .filter(p -> p.getFirstname().toLowerCase().contains(name.toLowerCase()) 
                      || p.getLastname().toLowerCase().contains(name.toLowerCase()))
            .toList();
}

Was macht dieser Code?

  • stream() – Konvertiert Liste zu Stream
  • filter() – Filtert Elemente
  • toLowerCase() – Macht Suche case-insensitive
  • contains() – Prüft ob Name enthalten ist
  • || – ODER-Verknüpfung (Firstname ODER Lastname)
  • toList() – Konvertiert Stream zurück zu Liste

Test:

bash

curl "http://localhost:8080/api/persons/search?name=Müller"
curl "http://localhost:8080/api/persons/search?name=Max"
curl "http://localhost:8080/api/persons/search?name=schmidt"

Bonus-Aufgaben

Weitere Ideen zum Üben:

  1. Sortierung implementieren:
    • GET /api/persons?sortBy=firstname
    • Tipp: Comparator.comparing(Person::getFirstname)
  2. Count-Endpoint:
    • GET /api/persons/count
    • Gibt Anzahl aller Personen zurück
  3. Random Person:
    • GET /api/persons/random
    • Gibt eine zufällige Person zurück
  4. Email-Domain Filter:
    • GET /api/persons?domain=example.com
    • Filtert nach Email-Domain

Probier dich aus! Das ist deine Spielwiese. 🎮

Wichtige Dokumentation


✅ Checkpoint: Hast du Tag 1 geschafft?

Grundlagen (🟢):

  • Spring Boot Projekt erstellt und gestartet
  • HelloController funktioniert (/hello)
  • Person-Klasse mit Gettern/Settern erstellt
  • PersonController gibt JSON zurück (/api/persons)
  • Eine Person nach ID abrufen funktioniert (/api/persons/1)
  • Nicht existierende ID gibt HTTP 404 zurück (/api/persons/999)

Professional (🟡):

  • Datafaker Dependency hinzugefügt
  • 100 Personen werden generiert
  • Deutsche Namen erscheinen in der API

Bonus (🔵):

  • Paginierung funktioniert (?page=0&size=10)
  • Suche nach Namen funktioniert (/search?name=...)

Quiz:

Frage 1: Was macht @SpringBootApplication genau?

Frage 2: Was ist der Unterschied zwischen @RestController und @Controller?

Frage 3: Warum braucht die Person-Klasse einen Default-Konstruktor?

Frage 4: Was macht ResponseEntity.notFound().build()?

Frage 5: Was ist der Unterschied zwischen @PathVariable und @RequestParam?

Alles ✅? Du bist bereit für Tag 2!

Nicht alles funktioniert?

  • Port 8080 belegt? Ändere in application.properties: server.port=9000
  • Maven Dependencies nicht geladen? Rechtsklick auf Projekt → Clean and Build
  • JSON kommt nicht? Prüfe ob spring-boot-starter-web in pom.xml ist
  • Datafaker Error? Prüfe Internet-Verbindung beim Maven Build

🔥 Elyndras Real Talk:

„Marcus hat letztens beim Kaffee gefragt: ‚Warum ist das so einfach? Wo ist der ganze Server-Setup-Kram?‘

Gute Frage. 2005 hättest du für diese 100-Zeilen-API einen Tag gebraucht:

  • Tomcat manuell konfigurieren
  • WAR-File bauen
  • Deployment-Descriptor schreiben (web.xml)
  • Servlet manuell registrieren

Spring Boot macht das in 2 Sekunden beim Start automatisch.

Das ist nicht Magie. Das ist Convention over Configuration.

Spring Boot schaut:

  • ‚Ah, spring-boot-starter-web ist da → Starte Tomcat‘
  • ‚Ah, @RestController gefunden → Registriere Routes‘
  • ‚Ah, Person-Objekt zurückgegeben → Konvertiere zu JSON‘

Alles automatisch. Punkt.

Eomma versteht das nicht. Sie sieht mich tippen und sagt: ‚So wenig Code? Das kann nicht funktionieren!‘

Doch, Eomma. Das ist Evolution. Und genau deshalb lieben wir Spring Boot.“


❓ FAQ (Häufige Fragen)

Q: Warum Port 8080?
A: Das ist Spring Boot’s Default. Du kannst es ändern in application.properties:

server.port=9000

Q: Muss ich Tomcat installieren?
A: Nein! Spring Boot hat einen embedded Tomcat. Der ist automatisch dabei.

Q: Warum heißt es @RestController und nicht @Controller?
A: @RestController = @Controller + @ResponseBody. Bedeutet: Gib Daten direkt zurück, nicht HTML-Views.

Q: Was ist der Unterschied zwischen @GetMapping und @RequestMapping?
A: @RequestMapping kann alles (GET, POST, PUT, DELETE). @GetMapping ist nur GET. Benutze @GetMapping – ist klarer!

Q: Warum braucht Person einen Default-Konstruktor?
A: Jackson (JSON Library) braucht ihn, um JSON → Java Objekt zu konvertieren. Ohne Default-Konstruktor: Error!

Q: In-Memory Liste ist doof, die Daten sind weg beim Neustart!
A: Korrekt! Das ist nur für Tag 1. Morgen lernen wir den Spring Container. Ab Tag 5 kommt eine echte Datenbank.

Q: Warum ResponseEntity statt einfach null zurückgeben?
A: null erzeugt eine leere Response mit Status 200 – das ist irreführend. ResponseEntity.notFound().build() gibt einen sauberen 404 zurück. REST-Clients erwarten klare Status-Codes!

Q: Was ist mit Marcus und diesem alten Holz?
A: Manchmal hilft es, über Code nachzudenken wie Marcus über Holz. Alte Balken haben ihre Geschichte. Legacy-Code auch. Aber neue Werkzeuge (wie Spring Boot) machen die Arbeit leichter. Das gilt für beide. 🪵

(Für mehr darüber, wie alte Strukturen neue Wege gehen… probier mal die Suche mit „herzschmerz“ auf java-developer.online. Nur so als Tipp.)

Q: Kann ich Spring Boot ohne NetBeans nutzen?
A: Klar! IntelliJ, Eclipse, VS Code – alles geht. Oder nur Terminal: mvn spring-boot:run

Q: Spring Boot 4.0 ist doch schon draußen – soll ich das nehmen?
A: Spring Boot 4.0 (November 2025) basiert auf Spring Framework 7 und bringt Breaking Changes mit: Kotlin 2.2 Baseline, JSpecify, neue Modularisierung. Für einen Basic-Kurs ist 3.4.x die richtige Wahl – stabil, bestens dokumentiert, und alle Konzepte die du hier lernst, gelten 1:1 auch für 4.x.


📚 Quiz-Lösungen

Hier sind die Antworten zum Quiz von oben:


Frage 1: Was macht @SpringBootApplication genau?

Antwort:

@SpringBootApplication ist eine Meta-Annotation, die drei Annotations kombiniert:

  1. @Configuration – Die Klasse kann Spring Beans definieren
  2. @EnableAutoConfiguration – Spring Boot konfiguriert automatisch basierend auf den Dependencies (z.B. Tomcat starten wenn spring-boot-starter-web vorhanden)
  3. @ComponentScan – Spring scannt das aktuelle Package und alle Sub-Packages nach Klassen mit @Component, @Service, @Controller, @RestController etc.

Frage 2: Was ist der Unterschied zwischen @RestController und @Controller?

Antwort:

@RestController = @Controller + @ResponseBody

  • @Controller gibt standardmäßig den Namen eines HTML-Templates zurück (z.B. für Thymeleaf)
  • @RestController gibt Daten direkt als Response Body zurück (JSON, XML, Text)
  • Für REST APIs: Immer @RestController
  • Für HTML-Seiten: @Controller (lernst du an Tag 3)

Frage 3: Warum braucht die Person-Klasse einen Default-Konstruktor?

Antwort:

Jackson (die JSON Library die Spring Boot automatisch mitbringt) braucht den Default-Konstruktor um JSON → Java Objekte zu konvertieren. Jackson erstellt zuerst eine leere Instanz mit new Person() und befüllt dann die Felder über die Setter-Methoden. Ohne Default-Konstruktor wirft Jackson eine Exception.


Frage 4: Was macht ResponseEntity.notFound().build()?

Antwort:

ResponseEntity gibt dir Kontrolle über die komplette HTTP Response:

  • ResponseEntity.ok(person) → Status 200 + Person als JSON Body
  • ResponseEntity.notFound().build() → Status 404 ohne Body
  • .build() baut die Response ohne Body zusammen

Das ist besser als null zurückzugeben, weil der Client einen klaren HTTP Status-Code bekommt statt einer leeren 200-Response.


Frage 5: Was ist der Unterschied zwischen @PathVariable und @RequestParam?

Antwort:

  • @PathVariable extrahiert Werte aus dem URL-Pfad: /api/persons/{id}/api/persons/42
  • @RequestParam extrahiert Werte aus Query-Parametern: /api/persons?page=0&size=10

Faustregel:

  • ID einer Ressource → @PathVariable (/persons/42)
  • Filter, Paginierung, Suche → @RequestParam (/persons?name=Max)

SQL Basic - Tag 1

Warum Datenbanken

Frage 1 von 10

Was ist das Hauptproblem von Excel bei größeren Datenmengen?

Frage 2 von 10

Wie viele Zeilen kann eine alte Excel-Datei (.xls) maximal speichern?

Frage 3 von 10

Was ist der Unterschied zwischen einer Datenbank und einem DBMS?

Frage 4 von 10

Was bedeutet das Client-Server-Prinzip bei Datenbanken?

Frage 5 von 10

Welche Datenbank wurde 2009 als Fork von MySQL erstellt?

Frage 6 von 10

Was passiert bei Redundanz (doppelten Daten) in einer Excel-Tabelle?

Frage 7 von 10

Was ist ein Vorteil von Datenbanken gegenüber Excel beim Teamwork?

Frage 8 von 10

Welches Datenbank-System nutzen wir im Kurs?

Frage 9 von 10

Wer hat 1970 das relationale Modell erfunden?

Frage 10 von 10

Was ist der Hauptvorteil von Datenbanken bei der Datensicherheit?

📅 Nächster Kurstag: Tag 2

Morgen im Kurs / Nächster Blogbeitrag:

„Spring Container & Dependency Injection“

Was du lernen wirst:

  • Den Spring Container verstehen (@Component, @Service, @Controller)
  • Was Spring Boot automatisch instanziiert
  • Dependency Injection richtig einsetzen
  • Service-Layer für Business-Logik erstellen
  • Best Practice: Constructor Injection
  • CRUD-Operationen (Create, Read, Update, Delete)

Warum wichtig? Der Spring Container ist das Herz von Spring Boot. Ohne ihn verstanden zu haben, bleibst du an der Oberfläche. Morgen schauen wir unter die Haube und du verstehst, was Spring Boot wirklich macht!

Brauchst du eine Pause?

Mach sie! Lass das heute sacken.

Tipp für heute Abend:

Spiel mit der API! Teste verschiedene Szenarien:

  • Was passiert bei /api/persons/0?
  • Was bei /api/persons/abc (keine Zahl)?
  • Was wenn du einen POST-Request an /api/persons schickst?

Learning by breaking things! 🔧

Voraussetzung: Tag 1 abgeschlossen

👉 Zum Blogbeitrag Tag 2


📥 Download & Ressourcen

Projekt zum Download:
👉 tag1-spring-boot-basic-v2.0.zip (Stand: Februar 2026)

Was ist im ZIP enthalten:

  • ✅ Vollständiges Maven-Projekt
  • ✅ HelloController (Hello World Endpoint)
  • ✅ PersonController (mit Datafaker, 100 Personen, ResponseEntity)
  • ✅ Person Model-Klasse (mit toString, equals, hashCode)
  • ✅ Paginierung und Suche (Bonus-Features)
  • ✅ Count- und Random-Endpoints (Bonus)
  • ✅ README.md mit Anleitungen
  • ✅ Konfigurierte pom.xml mit allen Dependencies

Versionen im Projekt:

KomponenteVersion
Spring Boot3.4.5
Java21
Datafaker2.5.4

Projekt starten:

bash

# ZIP entpacken
# In NetBeans öffnen: File → Open Project
# Oder im Terminal:
cd helloworldapi
mvn spring-boot:run

Probleme? Issue melden auf GitHub oder schreib mir: elyndra@java-developer.online


Du hast 10% des Kurses geschafft! 💪

Alle Blogbeiträge dieser Serie:
👉 Spring Boot Basic – Komplette Übersicht


Das war Tag 1 von Spring Boot Basic!

Du kannst jetzt:

  • ✅ Spring Boot Projekte mit Spring Initializr erstellen
  • ✅ REST Controller mit @RestController schreiben
  • ✅ HTTP GET Requests mit @GetMapping beantworten
  • ✅ Java-Objekte automatisch zu JSON konvertieren
  • ✅ Saubere HTTP-Antworten mit ResponseEntity zurückgeben
  • ✅ PathVariable und RequestParam einsetzen
  • ✅ Datafaker für Testdaten nutzen
  • ✅ Paginierung und Suche implementieren (Bonus)

Morgen lernst du den Spring Container und Dependency Injection – das Herz von Spring Boot! 🚀

Keep coding, keep learning!
🖖 Live long and prosper


Tags: #SpringBoot #RestAPI #Java #Tag1 #HelloWorld #JSON #Datafaker #BeginnerFriendly #ResponseEntity

Autor

  • Elyndra Valen

    28 Jahre alt, wurde kürzlich zur Senior Entwicklerin befördert nach 4 Jahren intensiver Java-Entwicklung. Elyndra kennt die wichtigsten Frameworks und Patterns, beginnt aber gerade erst, die tieferen Zusammenhänge und Architektur-Entscheidungen zu verstehen. Sie ist die Brücke zwischen Junior- und Senior-Welt im Team.