Zum Hauptinhalt springen

Woche 4, Tag 1 — Spring MVC Mental Model: DispatcherServlet, Controller, HandlerMapping und REST-Flow

Ziel

Heute verstehst du den Spring-MVC-Request-Flow.

Die Kernfragen:

  1. Was ist Spring MVC?
  2. Welches Problem löst Spring MVC?
  3. Was ist DispatcherServlet?
  4. Warum heißt DispatcherServlet Front Controller?
  5. Was ist ein Controller?
  6. Was ist HandlerMapping?
  7. Was ist HandlerAdapter?
  8. Was ist der Unterschied zwischen @Controller und @RestController?
  9. Wie wird aus einem HTTP-Request ein Java-Methodenaufruf?
  10. Wie wird aus einem Java-Objekt JSON?
  11. Welche typischen Prüfungsfallen gibt es?

1. Kurz-Wiederholung aus Woche 3

In Woche 3 hast du gelernt:

  • Spring Boot macht Spring einfacher zu konfigurieren, auszuführen, zu überwachen und zu deployen.
  • @SpringBootApplication enthält:

@Configuration
@EnableAutoConfiguration
@ComponentScan
  • Starters bringen Dependencies.
  • Auto-Configuration konfiguriert Beans.
  • Actuator hilft, eine laufende Anwendung zu überwachen.
  • SpringApplication.run(...) startet die Anwendung.

Merksatz:


Spring Boot startet die App und auto-konfiguriert gängige Infrastruktur.

Heute lernst du eine der wichtigsten Infrastrukturen in Web-Apps:


Spring MVC

2. Was ist Spring MVC?

Spring MVC ist das Spring-Framework-Modul zum Bau von Web-Anwendungen.

MVC steht für:


Model
View
Controller

In modernen REST APIs nutzt du Spring MVC oft ohne klassische serverseitig gerenderte Views.

Einfache Definition:

Spring MVC verarbeitet HTTP-Requests und mappt sie auf Java-Controller-Methoden.

Beispiel:

HTTP-Request:


GET /api/tasks

Java-Methode:


@GetMapping("/api/tasks")
public List<TaskDto> getTasks() {
return taskService.findAll();
}

Spring MVC verbindet diese beiden Welten.


3. Welches Problem löst Spring MVC?

Ohne Spring MVC müsstest du manuell handhaben:


HTTP-Routing
Request-Parsing
Query-Parameter
Path Variables
JSON-Request-Body-Parsing
JSON-Response-Schreiben
Status Codes
Header
Validation
Exception Handling
Content Negotiation

Spring MVC gibt dir einen strukturierten Weg, Web-Endpunkte zu schreiben.

Statt Low-Level-Servlet-Requests manuell zu parsen, schreibst du:


@RestController
@RequestMapping("/api/tasks")
public class TaskController {

@GetMapping
public List<TaskDto> listTasks() {
return List.of();
}
}

Merksatz:

Spring MVC mappt HTTP-Requests auf Java-Methoden und Java-Rückgabewerte zurück auf HTTP-Responses.


4. Spring MVC in einer Spring-Boot-App

In Spring Boot fügst du normalerweise hinzu:


implementation("org.springframework.boot:spring-boot-starter-web")

Das bringt:


Spring MVC
embedded Tomcat
Jackson JSON support
web auto-configuration
HTTP message converters

Dann auto-konfiguriert Spring Boot Spring MVC.

Du kannst Controller schreiben, ohne DispatcherServlet manuell zu konfigurieren.


5. Der große Request-Flow

Wenn ein Request reinkommt:


GET /api/tasks/123

Spring-MVC-Flow:


1. Client sendet HTTP-Request.
2. Embedded Tomcat empfängt ihn.
3. Request geht an DispatcherServlet.
4. DispatcherServlet fragt HandlerMapping: Welche Controller-Methode soll das handhaben?
5. HandlerAdapter ruft die Controller-Methode auf.
6. Controller ruft die Service-Schicht auf.
7. Service liefert Daten zurück.
8. Controller gibt ein Java-Objekt zurück.
9. HttpMessageConverter konvertiert das Java-Objekt zu JSON.
10. DispatcherServlet sendet die HTTP-Response.

Kurz-Merksatz:


Request -> DispatcherServlet -> HandlerMapping -> Controller -> Service -> JSON Response

6. Was ist DispatcherServlet?

DispatcherServlet ist das zentrale Servlet in Spring MVC.

Es empfängt eingehende HTTP-Requests und dispatcht sie an den richtigen Handler.

Einfache Definition:

DispatcherServlet ist der Front Controller von Spring MVC.

Es koordiniert den Request-Flow.

Es enthält nicht deine Business-Logik.

Es delegiert an andere Components.


7. Warum heißt es Front Controller?

Front Controller bedeutet:

Ein zentraler Einstiegspunkt empfängt Requests und delegiert sie an den richtigen Handler.

Statt dass jeder Controller Requests direkt empfängt, gehen Requests zuerst durch:


DispatcherServlet

Mental Model:


Client

DispatcherServlet

Richtige Controller-Methode

Merksatz:

DispatcherServlet ist der zentrale Einstiegspunkt für Spring-MVC-Requests.


8. Was macht DispatcherServlet?

DispatcherServlet koordiniert viele Dinge:


findet die richtige Handler-Methode
ruft den Handler über HandlerAdapter auf
verarbeitet Request-Parameter und Path Variables
arbeitet mit Message Converters
handhabt Exceptions
wählt Views in klassischem MVC
schreibt REST-Responses
koordiniert Interceptors
gibt HTTP-Response zurück

Wichtig:

DispatcherServlet koordiniert den Flow, macht aber nicht alles selbst.


9. Was ist ein Controller?

Ein Controller ist eine Spring Bean, die Web-Requests handhabt.

Beispiel:


@RestController
@RequestMapping("/api/tasks")
public class TaskController {

@GetMapping
public List<String> getTasks() {
return List.of("Task 1", "Task 2");
}
}

Dieser Controller handhabt:


GET /api/tasks

Einfache Definition:

Ein Controller enthält Methoden, die HTTP-Requests handhaben.


10. Controller sollten schlank sein

Ein Controller sollte normalerweise schlank sein.

Verantwortlichkeiten eines Controllers:


HTTP-Request empfangen
Request-Daten lesen
Service-Schicht aufrufen
Response-DTO zurückgeben
Status Code wählen

Ein Controller sollte keine schwere Business-Logik enthalten.

Schlecht:


@RestController
public class InvoiceController {

@PostMapping("/api/invoices")
public Invoice create(@RequestBody CreateInvoiceRequest request) {
// 200 lines of tax calculation here
// database logic here
// email sending here
return invoice;
}
}

Besser:


@RestController
@RequestMapping("/api/invoices")
public class InvoiceController {

private final InvoiceService invoiceService;

public InvoiceController(InvoiceService invoiceService) {
this.invoiceService = invoiceService;
}

@PostMapping
public InvoiceDto create(@RequestBody CreateInvoiceRequest request) {
return invoiceService.create(request);
}
}

Merksatz:

Controller handhaben HTTP. Services handhaben Business-Logik.


11. Was ist @RequestMapping?

@RequestMapping mappt HTTP-Requests auf Controller-Klassen oder -Methoden.

Mapping auf Klassenebene:


@RestController
@RequestMapping("/api/tasks")
public class TaskController {
}

Mapping auf Methodenebene:


@GetMapping("/{id}")
public TaskDto getTask(@PathVariable Long id) {
return taskService.findById(id);
}

Kombinierter Pfad:


GET /api/tasks/{id}

12. Shortcut-Mapping-Annotationen

Statt zu schreiben:


@RequestMapping(method = RequestMethod.GET)

bietet Spring Shortcuts:


@GetMapping
@PostMapping
@PutMapping
@PatchMapping
@DeleteMapping

Beispiele:


@GetMapping("/tasks")
@PostMapping("/tasks")
@PutMapping("/tasks/{id}")
@PatchMapping("/tasks/{id}")
@DeleteMapping("/tasks/{id}")

Diese passen zu HTTP-Methoden.


13. REST-Beispiel


@RestController
@RequestMapping("/api/tasks")
public class TaskController {

@GetMapping
public List<TaskDto> list() {
return taskService.findAll();
}

@GetMapping("/{id}")
public TaskDto get(@PathVariable Long id) {
return taskService.findById(id);
}

@PostMapping
public TaskDto create(@RequestBody CreateTaskRequest request) {
return taskService.create(request);
}

@DeleteMapping("/{id}")
public void delete(@PathVariable Long id) {
taskService.delete(id);
}
}

Mappings:


GET /api/tasks -> list()
GET /api/tasks/123 -> get(123)
POST /api/tasks -> create(request)
DELETE /api/tasks/123 -> delete(123)

14. Was ist HandlerMapping?

HandlerMapping findet den richtigen Handler für einen Request.

Einfache Definition:

HandlerMapping mappt einen HTTP-Request auf eine Controller-Methode.

Beispiel-Request:


GET /api/tasks/123

Controller:


@GetMapping("/api/tasks/{id}")
public TaskDto getTask(@PathVariable Long id) {
}

HandlerMapping sagt:


Dieser Request soll von getTask(...) gehandhabt werden

Merksatz:

HandlerMapping beantwortet: Welche Controller-Methode soll diesen Request handhaben?


15. Was ist HandlerAdapter?

HandlerAdapter ruft die ausgewählte Handler-Methode auf.

Einfache Definition:

HandlerAdapter weiß, wie die von HandlerMapping ausgewählte Controller-Methode aufgerufen wird.

Warum nötig?

Weil Spring MVC verschiedene Handler-Arten unterstützt.

DispatcherServlet weiß nicht direkt, wie jeder mögliche Handler-Typ aufgerufen wird.

Deshalb delegiert es den Aufruf an einen HandlerAdapter.

Merksatz:

HandlerMapping findet die Methode. HandlerAdapter ruft die Methode auf.


16. HandlerMapping vs. HandlerAdapter

ComponentAufgabe
HandlerMappingfindet den Handler für den Request
HandlerAdapterruft den Handler auf
DispatcherServletkoordiniert den gesamten Flow

Merksatz für die Prüfung:


Mapping finds.
Adapter invokes.
Dispatcher coordinates.

17. Was ist ein Handler?

In Spring MVC ist ein Handler normalerweise eine Controller-Methode.

Beispiel:


@GetMapping("/api/tasks/{id}")
public TaskDto getTask(@PathVariable Long id) {
return taskService.findById(id);
}

Diese Methode ist der Handler für:


GET /api/tasks/{id}

Wenn Spring MVC „Handler“ sagt, denk an:


Controller-Methode

Meistens.


18. Was ist @Controller?

@Controller markiert eine Klasse als Spring-MVC-Controller.

Beispiel:


@Controller
public class PageController {

@GetMapping("/home")
public String home() {
return "home";
}
}

In klassischem MVC bedeutet die Rückgabe von "home":


Rendere die View namens home.

Zum Beispiel:


templates/home.html

19. Was ist @RestController?

@RestController wird für REST APIs genutzt.

Beispiel:


@RestController
public class TaskController {

@GetMapping("/api/tasks")
public List<String> tasks() {
return List.of("Task 1", "Task 2");
}
}

Der Rückgabewert wird direkt in den HTTP-Response-Body geschrieben.

Diese Java-Liste wird also zu JSON.

Merksatz:

@RestController gibt Daten zurück, keine Views.


20. @RestController = @Controller + @ResponseBody

Sehr wichtiger Prüfungssatz:


@RestController = @Controller + @ResponseBody

Bedeutung:


@RestController
public class TaskController {
}

ist konzeptionell ähnlich zu:


@Controller
@ResponseBody
public class TaskController {
}

@ResponseBody bedeutet:

Schreibe den Methoden-Rückgabewert direkt in den HTTP-Response-Body.


21. @Controller vs. @RestController

Thema@Controller@RestController
Typischer Einsatzserverseitig gerenderte ViewsREST APIs
String-RückgabeView-NameResponse-Body-Text
JSON-Responsebraucht @ResponseBodyautomatisch
Enthält @ResponseBodyneinja

Beispiel mit @Controller:


@Controller
public class PageController {

@GetMapping("/home")
public String home() {
return "home";
}
}

Spring sucht eine View namens:


home

Beispiel mit @RestController:


@RestController
public class ApiController {

@GetMapping("/api/hello")
public String hello() {
return "hello";
}
}

Spring gibt den Body zurück:


hello

22. Was ist @ResponseBody?

@ResponseBody sagt Spring:

Behandle den Rückgabewert nicht als View-Namen. Schreibe ihn direkt in den HTTP-Response-Body.

Beispiel:


@Controller
public class TaskController {

@GetMapping("/api/tasks")
@ResponseBody
public List<String> tasks() {
return List.of("Task 1", "Task 2");
}
}

Das liefert JSON.

Mit @RestController musst du @ResponseBody nicht auf jede Methode setzen.


23. Wie Java-Objekte zu JSON werden

Controller:


@GetMapping("/api/tasks")
public List<TaskDto> tasks() {
return List.of(
new TaskDto(1L, "Learn Spring MVC"),
new TaskDto(2L, "Practice REST")
);
}

DTO:


public record TaskDto(Long id, String title) {
}

Response:


[
{
"id": 1,
"title": "Learn Spring MVC"
},
{
"id": 2,
"title": "Practice REST"
}
]

Wer konvertiert das?


HttpMessageConverter

Normalerweise mit Jackson für JSON.


24. Was ist HttpMessageConverter?

HttpMessageConverter konvertiert zwischen HTTP-Body-Daten und Java-Objekten.

Zwei Richtungen:


HTTP-Request-Body -> Java-Objekt
Java-Objekt -> HTTP-Response-Body

Beispiel-Request:


{
"title": "Learn Spring"
}

Java-Objekt:


public record CreateTaskRequest(String title) {
}

Controller:


@PostMapping("/api/tasks")
public TaskDto create(@RequestBody CreateTaskRequest request) {
return taskService.create(request);
}

Spring nutzt einen HttpMessageConverter, um JSON in CreateTaskRequest zu konvertieren.


25. Jackson und JSON

In den meisten Spring-Boot-MVC-Apps übernimmt Jackson die JSON-Konvertierung.

Wenn du hinzufügst:


implementation("org.springframework.boot:spring-boot-starter-web")

bringt Spring Boot normalerweise Jackson-Support mit.

Deshalb funktioniert das:


@RestController
public class UserController {

@GetMapping("/api/users/1")
public UserDto getUser() {
return new UserDto(1L, "Steve");
}
}

Response:


{
"id": 1,
"name": "Steve"
}

Merksatz:

Jackson konvertiert Java-Objekte zu JSON und JSON zu Java-Objekten.


26. Was ist @RequestBody?

@RequestBody sagt Spring:

Lies den HTTP-Request-Body und konvertiere ihn in ein Java-Objekt.

Beispiel:


POST /api/tasks
Content-Type: application/json

{
"title": "Learn Spring MVC"
}

Controller:


@PostMapping("/api/tasks")
public TaskDto create(@RequestBody CreateTaskRequest request) {
return taskService.create(request);
}

Spring konvertiert JSON in:


CreateTaskRequest

27. Was ist @PathVariable?

@PathVariable liest einen Wert aus dem URL-Pfad.

Beispiel:


GET /api/tasks/123

Controller:


@GetMapping("/api/tasks/{id}")
public TaskDto getTask(@PathVariable Long id) {
return taskService.findById(id);
}

Spring bindet:


123 -> id

28. Benanntes @PathVariable

Wenn der Variablenname anders ist:


@GetMapping("/api/tasks/{taskId}")
public TaskDto getTask(@PathVariable("taskId") Long id) {
return taskService.findById(id);
}

Path Variable:


taskId

Java-Parameter:


id

Spring bindet taskId an id.


29. Was ist @RequestParam?

@RequestParam liest Query-Parameter.

Beispiel:


GET /api/tasks?page=0&size=20

Controller:


@GetMapping("/api/tasks")
public List<TaskDto> listTasks(
@RequestParam int page,
@RequestParam int size
) {
return taskService.findPage(page, size);
}

Spring bindet:


page=0 -> page
size=20 -> size

30. Optionales @RequestParam

Beispiel:


@GetMapping("/api/tasks")
public List<TaskDto> listTasks(
@RequestParam(required = false) String status
) {
return taskService.findByStatus(status);
}

Wenn der Query-Parameter fehlt:


status = null

Besser mit Default:


@GetMapping("/api/tasks")
public List<TaskDto> listTasks(
@RequestParam(defaultValue = "OPEN") String status
) {
return taskService.findByStatus(status);
}

31. @RequestBody vs. @RequestParam vs. @PathVariable

AnnotationLiest ausBeispiel
@PathVariableURL-Pfad/tasks/123
@RequestParamQuery String/tasks?page=0
@RequestBodyHTTP-BodyJSON-Body

Merksatz:


PathVariable = path.
RequestParam = query.
RequestBody = body.

32. Vollständiges REST-Flow-Beispiel

Request:


POST /api/tasks
Content-Type: application/json

{
"title": "Learn DispatcherServlet"
}

Controller:


@RestController
@RequestMapping("/api/tasks")
public class TaskController {

private final TaskService taskService;

public TaskController(TaskService taskService) {
this.taskService = taskService;
}

@PostMapping
public TaskDto create(@RequestBody CreateTaskRequest request) {
return taskService.create(request);
}
}

Request-DTO:


public record CreateTaskRequest(String title) {
}

Response-DTO:


public record TaskDto(Long id, String title) {
}

Flow:


1. Client sendet POST /api/tasks.
2. Tomcat empfängt den Request.
3. DispatcherServlet empfängt den Request.
4. HandlerMapping findet TaskController.create().
5. HttpMessageConverter konvertiert den JSON-Body zu CreateTaskRequest.
6. HandlerAdapter ruft create(request) auf.
7. Controller ruft TaskService auf.
8. Service liefert TaskDto zurück.
9. HttpMessageConverter konvertiert TaskDto zu JSON.
10. DispatcherServlet sendet die HTTP-Response.

33. Status Codes zurückgeben

Standardmäßig:


@PostMapping
public TaskDto create(@RequestBody CreateTaskRequest request) {
return taskService.create(request);
}

liefert oft:


HTTP 200 OK

Für Create-Operationen aber besser:


HTTP 201 Created

Nutze ResponseEntity:


@PostMapping
public ResponseEntity<TaskDto> create(@RequestBody CreateTaskRequest request) {
TaskDto created = taskService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}

34. ResponseEntity

Mit ResponseEntity steuerst du:


Status Code
Header
Body

Beispiel:


@GetMapping("/{id}")
public ResponseEntity<TaskDto> getTask(@PathVariable Long id) {
TaskDto task = taskService.findById(id);
return ResponseEntity.ok(task);
}

Beispiel No Content:


@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteTask(@PathVariable Long id) {
taskService.delete(id);
return ResponseEntity.noContent().build();
}

Response:


HTTP 204 No Content

35. @ResponseStatus

Ein anderer Weg, den Status zu setzen:


@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public TaskDto create(@RequestBody CreateTaskRequest request) {
return taskService.create(request);
}

Das liefert immer:


201 Created

außer eine Exception ändert die Response.

Nutze ResponseEntity, wenn du mehr Kontrolle brauchst.

Nutze @ResponseStatus, wenn der Status fest und einfach ist.


36. Häufige HTTP-Status-Codes in REST

StatusBedeutung
200 OKerfolgreicher Request mit Response Body
201 CreatedRessource erstellt
204 No Contenterfolgreicher Request ohne Body
400 Bad Requestungültiger Client-Request
401 UnauthorizedAuthentifizierung erforderlich oder fehlgeschlagen
403 Forbiddenauthentifiziert, aber nicht berechtigt
404 Not FoundRessource nicht gefunden
409 ConflictKonflikt mit dem aktuellen Zustand
500 Internal Server ErrorServer-Fehler

Für die Zertifizierung solltest du die häufigsten kennen.


37. Was passiert, wenn kein Mapping passt?

Request:


GET /api/unknown

Es gibt kein Controller-Mapping.

Spring MVC liefert normalerweise:


404 Not Found

Weil HandlerMapping keinen passenden Handler finden konnte.

Merksatz:

Kein passender Handler bedeutet normalerweise 404.


38. Was passiert, wenn die Methode nicht unterstützt wird?

Controller:


@GetMapping("/api/tasks")
public List<TaskDto> list() {
return taskService.findAll();
}

Request:


POST /api/tasks

Wenn kein POST-Mapping existiert, ist die Response normalerweise:


405 Method Not Allowed

Merksatz:

Pfad existiert, aber HTTP-Methode ist falsch: 405.


39. Was passiert, wenn JSON nicht geparst werden kann?

Request:


POST /api/tasks
Content-Type: application/json

{
"title":
}

Ungültiges JSON.

Spring kann den Body nicht in ein Java-Objekt konvertieren.

Die Response ist normalerweise:


400 Bad Request

Weil der Client ungültige Eingaben gesendet hat.


40. Was passiert, wenn die Typkonvertierung fehlschlägt?

Request:


GET /api/tasks/abc

Controller erwartet:


@GetMapping("/api/tasks/{id}")
public TaskDto getTask(@PathVariable Long id) {
}

Spring kann nicht konvertieren:


abc -> Long

Die Response ist normalerweise:


400 Bad Request

41. @RequestMapping-Bedingungen

Mappings können auf mehr als nur den Pfad passen.

Sie können passen auf:


Pfad
HTTP-Methode
Request-Parameter
Header
consumes Content Type
produces Content Type

Beispiel:


@PostMapping(
value = "/api/tasks",
consumes = "application/json",
produces = "application/json"
)
public TaskDto create(@RequestBody CreateTaskRequest request) {
return taskService.create(request);
}

Bedeutung:


JSON-Request-Body akzeptieren.
JSON-Response zurückgeben.

42. Content Negotiation

Content Negotiation bedeutet:

Spring entscheidet, welches Response-Format produziert wird — basierend auf Request-Headern und verfügbaren Converters.

Beispiel-Request-Header:


Accept: application/json

Spring wählt JSON, wenn es JSON produzieren kann.

Für normale REST APIs ist JSON üblich.

Spring nutzt dafür HttpMessageConverter.

Merksatz:

Content Negotiation hilft, das Response-Format zu wählen.


43. consumes und produces

consumes bedeutet:


Welchen Request-Content-Type diese Methode akzeptiert.

produces bedeutet:


Welchen Response-Content-Type diese Methode zurückgibt.

Beispiel:


@PostMapping(
value = "/api/tasks",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE
)
public TaskDto create(@RequestBody CreateTaskRequest request) {
return taskService.create(request);
}

44. Typische REST-Controller-Struktur


@RestController
@RequestMapping("/api/tasks")
public class TaskController {

private final TaskService taskService;

public TaskController(TaskService taskService) {
this.taskService = taskService;
}

@GetMapping
public List<TaskDto> list() {
return taskService.findAll();
}

@GetMapping("/{id}")
public TaskDto get(@PathVariable Long id) {
return taskService.findById(id);
}

@PostMapping
public ResponseEntity<TaskDto> create(@RequestBody CreateTaskRequest request) {
TaskDto created = taskService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
taskService.delete(id);
return ResponseEntity.noContent().build();
}
}

Das ist ein sauberer, grundlegender REST-Controller.


45. DTOs vs. Entities

Vermeide es, JPA-Entities direkt aus Controllern zurückzugeben.

Besser:


Controller gibt DTOs zurück.
Service arbeitet mit Domain-Logik.
Repository arbeitet mit Entities.

Schlecht:


@GetMapping("/api/users/{id}")
public UserEntity getUser(@PathVariable Long id) {
return userRepository.findById(id).orElseThrow();
}

Besser:


@GetMapping("/api/users/{id}")
public UserDto getUser(@PathVariable Long id) {
return userService.findById(id);
}

Warum?


interne Datenbankstruktur nicht exponieren
Lazy-Loading-Serialisierungsprobleme vermeiden
Response-Form steuern
sensible Felder nicht leaken
API-Vertrag vom Persistence-Model trennen

Merksatz:

REST APIs sollten normalerweise DTOs exponieren, nicht Entities.


46. Spring MVC vs. Spring WebFlux

Spring MVC:


servlet-basiert
blocking Model
nutzt häufig Tomcat
Starter: spring-boot-starter-web

Spring WebFlux:


reactive
non-blocking Model
nutzt häufig Reactor Netty
Starter: spring-boot-starter-webflux

Für normale REST APIs und die meisten Prüfungsfragen:


Spring MVC + spring-boot-starter-web

Merksatz:

Spring MVC ist servlet-basiert. WebFlux ist reactive.


47. Typische Prüfungsfallen

Falle 1

DispatcherServlet ist nicht dein Controller.

Es ist der zentrale Front Controller, der Requests an Handler dispatcht.


Falle 2

HandlerMapping ruft den Controller nicht auf.

Es findet den passenden Handler.


Falle 3

HandlerAdapter ruft den Handler auf.


Falle 4

@RestController ist @Controller plus @ResponseBody.


Falle 5

Mit @Controller bedeutet ein zurückgegebener String normalerweise View-Namen.

Mit @RestController bedeutet ein zurückgegebener String Response Body.


Falle 6

@RequestBody liest den HTTP-Body.

@RequestParam liest Query-Parameter.

@PathVariable liest Pfadwerte.


Falle 7

Java-Objekte werden über HttpMessageConverter zu JSON — normalerweise mit Jackson.


Falle 8

Kein passender Pfad bedeutet normalerweise 404.

Falsche HTTP-Methode bedeutet normalerweise 405.

Ungültiger Request-Body oder Typkonvertierung bedeutet normalerweise 400.


Falle 9

Controller sollten schlank sein.

Business-Logik gehört in Services.


Falle 10

In den meisten echten Projekten solltest du JPA-Entities nicht direkt aus REST APIs exponieren.


48. Prüfungsfrage: Spring MVC

Frage:

Was ist Spring MVC?

Antwort:

Spring MVC ist das Spring-Framework-Modul zum Bau von Web-Anwendungen. Es mappt HTTP-Requests auf Java-Controller-Methoden und hilft bei Request-Daten, Response-Daten, Validation, Exceptions, Views und REST-Responses.


49. Prüfungsfrage: DispatcherServlet

Frage:

Was ist DispatcherServlet?

Antwort:

DispatcherServlet ist der zentrale Front Controller in Spring MVC. Es empfängt eingehende HTTP-Requests und koordiniert den Prozess: den richtigen Handler finden, ihn aufrufen, das Ergebnis verarbeiten und eine HTTP-Response zurückgeben.


50. Prüfungsfrage: HandlerMapping

Frage:

Was macht HandlerMapping?

Antwort:

HandlerMapping findet, welcher Handler — normalerweise eine Controller-Methode — einen gegebenen HTTP-Request handhaben soll.


51. Prüfungsfrage: HandlerAdapter

Frage:

Was macht HandlerAdapter?

Antwort:

HandlerAdapter ruft die von HandlerMapping ausgewählte Handler-Methode auf.


52. Prüfungsfrage: @Controller vs. @RestController

Frage:

Was ist der Unterschied zwischen @Controller und @RestController?

Antwort:

@Controller wird häufig für klassische MVC-Controller genutzt, die View-Namen zurückgeben. @RestController wird für REST APIs genutzt und schreibt Rückgabewerte direkt in den HTTP-Response-Body. @RestController entspricht @Controller plus @ResponseBody.


53. Prüfungsfrage: @ResponseBody

Frage:

Was macht @ResponseBody?

Antwort:

@ResponseBody sagt Spring, den Methoden-Rückgabewert direkt in den HTTP-Response-Body zu schreiben — statt ihn als View-Namen zu behandeln.


54. Prüfungsfrage: JSON-Konvertierung

Frage:

Wie konvertiert Spring Java-Objekte in REST-Controllern zu JSON?

Antwort:

Spring nutzt HttpMessageConverters. In einer typischen Spring-Boot-MVC-Anwendung konvertiert Jackson Java-Objekte zu JSON und JSON-Request-Bodies zu Java-Objekten.


55. Prüfungsfrage: @RequestBody

Frage:

Was macht @RequestBody?

Antwort:

@RequestBody sagt Spring, den HTTP-Request-Body zu lesen und mit einem HttpMessageConverter in ein Java-Objekt zu konvertieren.


56. Prüfungsfrage: @PathVariable

Frage:

Was macht @PathVariable?

Antwort:

@PathVariable bindet einen Wert aus dem URL-Pfad an einen Controller-Methoden-Parameter.


57. Prüfungsfrage: @RequestParam

Frage:

Was macht @RequestParam?

Antwort:

@RequestParam bindet einen Query-Parameter aus der Request-URL an einen Controller-Methoden-Parameter.


58. Prüfungsfrage: ResponseEntity

Frage:

Warum ResponseEntity nutzen?

Antwort:

ResponseEntity erlaubt einer Controller-Methode, HTTP-Status-Code, Response-Header und Response-Body zu steuern.


59. Prüfungsfrage: Kein Mapping

Frage:

Was passiert normalerweise, wenn kein Controller-Mapping zu einem Request passt?

Antwort:

Spring MVC liefert normalerweise 404 Not Found.


60. Prüfungsfrage: Falsche HTTP-Methode

Frage:

Was passiert normalerweise, wenn der Pfad existiert, aber die HTTP-Methode nicht unterstützt wird?

Antwort:

Spring MVC liefert normalerweise 405 Method Not Allowed.


61. Interview-Antwort

Frage:

Explain the Spring MVC request flow.

Gute Antwort:

Wenn ein HTTP-Request reinkommt, empfängt der embedded Servlet Container ihn und leitet ihn an Spring MVCs DispatcherServlet weiter. DispatcherServlet fragt HandlerMapping, welche Controller-Methode zuständig ist. Dann ruft ein HandlerAdapter diese Methode auf. Der Controller ruft normalerweise einen Service auf und gibt ein Java-Objekt oder ResponseEntity zurück. Für REST APIs konvertiert ein HttpMessageConverter — normalerweise mit Jackson — das Java-Objekt zu JSON. Zum Schluss sendet DispatcherServlet die HTTP-Response an den Client zurück.


62. Interview-Antwort

Frage:

What is the role of DispatcherServlet?

Gute Antwort:

DispatcherServlet ist der Front Controller von Spring MVC. Es empfängt eingehende HTTP-Requests und koordiniert die Request-Verarbeitung. Es delegiert an HandlerMapping, um den richtigen Handler zu finden, nutzt einen HandlerAdapter zum Aufruf, arbeitet mit Message Converters und Exception Handlers und gibt die finale HTTP-Response zurück. Es ist der zentrale Einstiegspunkt für Spring-MVC-Requests.


63. Interview-Antwort

Frage:

What is the difference between @Controller and @RestController?

Gute Antwort:

@Controller markiert eine Klasse als Spring-MVC-Controller — oft für klassische serverseitig gerenderte Views. Gibt eine Methode einen String zurück, kann Spring ihn als View-Namen behandeln. @RestController wird für REST APIs genutzt. Es enthält @ResponseBody, sodass Methoden-Rückgabewerte direkt in den HTTP-Response-Body geschrieben werden — normalerweise als JSON.


64. Interview-Antwort

Frage:

How does Spring handle JSON request and response bodies?

Gute Antwort:

Spring nutzt HttpMessageConverters, um zwischen HTTP-Bodies und Java-Objekten zu konvertieren. In einer typischen Spring-Boot-MVC-Anwendung konfiguriert der Web-Starter Jackson automatisch. Für einen Request-Body sagt @RequestBody Spring, JSON in ein Java-Objekt zu konvertieren. Für einen Response-Body konvertiert Spring das zurückgegebene Java-Objekt zu JSON.


65. Interview-Antwort

Frage:

How should a REST controller be structured?

Gute Antwort:

Ein REST-Controller sollte schlank sein. Er sollte HTTP-Themen handhaben: Path Variables, Query-Parameter, Request Bodies, Status Codes und Response-DTOs. Business-Logik delegiert er an die Service-Schicht. Die Service-Schicht enthält Business-Regeln, Repositories handhaben Persistence. Controller sollten normalerweise DTOs statt JPA-Entities zurückgeben, um den API-Vertrag vom Datenbankmodell zu trennen.


66. Kleine Code-Übung

Erstelle einen Controller:


@RestController
@RequestMapping("/api/tasks")
public class TaskController {

@GetMapping("/{id}")
public TaskDto getTask(@PathVariable Long id) {
return new TaskDto(id, "Learn Spring MVC");
}

@PostMapping
public ResponseEntity<TaskDto> createTask(@RequestBody CreateTaskRequest request) {
TaskDto created = new TaskDto(1L, request.title());
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
}

DTOs:


public record TaskDto(Long id, String title) {
}

public record CreateTaskRequest(String title) {
}

Fragen:

  1. Welche Methode handhabt GET /api/tasks/5?
  2. Woher kommt id?
  3. Woher kommt CreateTaskRequest?
  4. Welchen Status liefert createTask?
  5. Wer konvertiert TaskDto zu JSON?

Antworten:

  1. getTask
  2. Aus der Path Variable {id}
  3. Aus dem JSON-Request-Body über @RequestBody
  4. 201 Created
  5. Ein HttpMessageConverter, normalerweise mit Jackson

67. Kleine Bug-Übung 1

Problem:


@Controller
@RequestMapping("/api/hello")
public class HelloController {

@GetMapping
public String hello() {
return "hello";
}
}

Erwarteter Response Body:


hello

Aber Spring sucht eine View namens hello.

Frage:

Was ist falsch?

Antwort:

Die Klasse nutzt @Controller. Ein zurückgegebener String wird deshalb als View-Namen behandelt — außer du nutzt @ResponseBody.

Fix-Option 1:


@RestController
@RequestMapping("/api/hello")
public class HelloController {

@GetMapping
public String hello() {
return "hello";
}
}

Fix-Option 2:


@Controller
@RequestMapping("/api/hello")
public class HelloController {

@GetMapping
@ResponseBody
public String hello() {
return "hello";
}
}

68. Kleine Bug-Übung 2

Problem:

Request:


GET /api/tasks/abc

Controller:


@GetMapping("/api/tasks/{id}")
public TaskDto getTask(@PathVariable Long id) {
return taskService.findById(id);
}

Frage:

Was passiert?

Antwort:

Spring versucht, abc in Long zu konvertieren — die Konvertierung schlägt fehl. Die Response ist normalerweise 400 Bad Request.


69. Kleine Bug-Übung 3

Problem:

Request:


POST /api/tasks
Content-Type: application/json

{
"title":
}

Controller:


@PostMapping("/api/tasks")
public TaskDto create(@RequestBody CreateTaskRequest request) {
return taskService.create(request);
}

Frage:

Was passiert?

Antwort:

Das JSON ist ungültig. Spring kann den Request-Body nicht in CreateTaskRequest konvertieren. Die Response ist normalerweise 400 Bad Request.


Übungsfragen

Frage 1

Was ist Spring MVC?

Antwort:

Spring MVC ist das Spring-Framework-Modul zum Bau von Web-Anwendungen. Es mappt HTTP-Requests auf Java-Controller-Methoden und hilft bei Request-Daten, Responses, Validation, Exceptions, Views und REST APIs.


Frage 2

Welches Problem löst Spring MVC?

Antwort:

Spring MVC löst das Problem, HTTP-Routing, Request-Parsing, Response-Schreiben, JSON-Konvertierung, Status Codes, Validation und Exception Handling manuell handhaben zu müssen.


Frage 3

Was ist DispatcherServlet?

Antwort:

DispatcherServlet ist der zentrale Front Controller in Spring MVC. Es empfängt eingehende HTTP-Requests und koordiniert die Request-Verarbeitung.


Frage 4

Warum heißt DispatcherServlet Front Controller?

Antwort:

Es heißt Front Controller, weil es der zentrale Einstiegspunkt für Spring-MVC-Requests ist und an die richtigen Handler delegiert.


Frage 5

Was ist ein Controller?

Antwort:

Ein Controller ist eine Spring Bean mit Methoden zum Handhaben von HTTP-Requests.


Frage 6

Was macht HandlerMapping?

Antwort:

HandlerMapping findet, welcher Handler — normalerweise eine Controller-Methode — einen Request handhaben soll.


Frage 7

Was macht HandlerAdapter?

Antwort:

HandlerAdapter ruft den von HandlerMapping ausgewählten Handler auf.


Frage 8

Was ist der Unterschied zwischen HandlerMapping und HandlerAdapter?

Antwort:

HandlerMapping findet den Handler. HandlerAdapter ruft den Handler auf.


Frage 9

Was ist @RequestMapping?

Antwort:

@RequestMapping mappt HTTP-Requests auf Controller-Klassen oder -Methoden — basierend auf Pfad, Methode, Headern, Parametern, consumes oder produces.


Frage 10

Nenne fünf Shortcut-Mapping-Annotationen.

Antwort:

Fünf Shortcut-Annotationen sind:


@GetMapping
@PostMapping
@PutMapping
@PatchMapping
@DeleteMapping

Frage 11

Was ist der Unterschied zwischen @Controller und @RestController?

Antwort:

@Controller wird oft für klassisches MVC genutzt und kann View-Namen zurückgeben. @RestController wird für REST APIs genutzt und schreibt Rückgabewerte direkt in den Response Body. @RestController entspricht @Controller plus @ResponseBody.


Frage 12

Was macht @ResponseBody?

Antwort:

@ResponseBody sagt Spring, den Methoden-Rückgabewert direkt in den HTTP-Response-Body zu schreiben — statt ihn als View-Namen zu behandeln.


Frage 13

Was macht @RequestBody?

Antwort:

@RequestBody sagt Spring, den HTTP-Request-Body zu lesen und in ein Java-Objekt zu konvertieren.


Frage 14

Was macht @PathVariable?

Antwort:

@PathVariable bindet einen Wert aus dem URL-Pfad an einen Methoden-Parameter.


Frage 15

Was macht @RequestParam?

Antwort:

@RequestParam bindet einen Query-Parameter aus der URL an einen Methoden-Parameter.


Frage 16

Was ist HttpMessageConverter?

Antwort:

HttpMessageConverter konvertiert zwischen HTTP-Request-/Response-Bodies und Java-Objekten.


Frage 17

Wie konvertiert Spring normalerweise Java-Objekte zu JSON?

Antwort:

In einer typischen Spring-Boot-MVC-App nutzt Spring Jackson über einen HttpMessageConverter, um Java-Objekte zu JSON zu konvertieren.


Frage 18

Wofür wird ResponseEntity genutzt?

Antwort:

ResponseEntity steuert HTTP-Status-Code, Header und Response-Body.


Frage 19

Was passiert normalerweise, wenn kein Mapping passt?

Antwort:

Wenn kein Mapping passt, liefert Spring MVC normalerweise 404 Not Found.


Frage 20

Warum sollten Controller normalerweise schlank sein?

Antwort:

Controller sollten schlank sein, weil sie HTTP-Themen handhaben und Business-Logik an Services delegieren sollten. Das hält den Code sauber, testbar und wartbar.

Merksätze zum Mitnehmen

  • Spring MVC mappt HTTP-Requests auf Java-Controller-Methoden.
  • DispatcherServlet ist der Front Controller von Spring MVC.
  • DispatcherServlet koordiniert den Request-Flow.
  • HandlerMapping findet den Handler.
  • HandlerAdapter ruft den Handler auf.
  • Ein Controller handhabt HTTP-Requests.
  • Controller sollten normalerweise schlank sein.
  • @RestController entspricht @Controller plus @ResponseBody.
  • @Controller kann View-Namen zurückgeben.
  • @RestController gibt Response Bodies zurück.
  • @RequestBody liest den HTTP-Body.
  • @PathVariable liest Pfadwerte.
  • @RequestParam liest Query-Parameter.
  • HttpMessageConverter konvertiert zwischen HTTP-Bodies und Java-Objekten.
  • Jackson konvertiert normalerweise Java-Objekte zu JSON.
  • ResponseEntity steuert Status, Header und Body.
  • Kein passendes Mapping bedeutet normalerweise 404.
  • Falsche HTTP-Methode bedeutet normalerweise 405.
  • Ungültiger Request-Body oder Typkonvertierung bedeutet normalerweise 400.
  • REST-Controller sollten normalerweise DTOs zurückgeben, nicht JPA-Entities.