33 Model-View-Controller (MVC)

Das Model-View-Controller (MVC)-Muster ist ein weit verbreitetes Entwurfsmuster, das die Benutzeroberfläche (View), die Geschäftslogik (Controller) und die Daten (Model) voneinander trennt. In Spring Boot wird das MVC-Muster durch das Spring Web-Modul unterstützt, das leistungsfähige Werkzeuge zur Implementierung von Webanwendungen bietet. Die Trennung der Schichten erleichtert die Wartung und Erweiterbarkeit von Webanwendungen und fördert die klare Trennung von Verantwortlichkeiten.

In diesem Kapitel wird das MVC-Muster in Spring Boot detailliert erklärt, mit Schwerpunkt auf der Implementierung von Controllern, der Verarbeitung von Modellen und der Darstellung von Daten in Views.

33.1 Überblick über das MVC-Muster

Das MVC-Muster gliedert eine Webanwendung in drei Hauptkomponenten:

  1. Model: Das Model repräsentiert die Daten der Anwendung. Es enthält die Geschäftslogik und die Regeln zur Manipulation von Daten.
  2. View: Die View stellt die Benutzerschnittstelle dar. Sie wird verwendet, um die Daten aus dem Model in einem ansprechenden Format an den Benutzer zu präsentieren.
  3. Controller: Der Controller fungiert als Vermittler zwischen View und Model. Er verarbeitet Benutzeranfragen, aktualisiert das Model und leitet die Daten an die View weiter.

33.1.1 MVC in Spring Boot

In Spring Boot wird das MVC-Muster durch das Spring Web-Modul unterstützt. Hier die typische Interaktion zwischen den Komponenten in einer Spring Boot MVC-Anwendung:

  1. Der Benutzer sendet eine HTTP-Anfrage (z.B. durch einen Webbrowser).
  2. Der Controller empfängt die Anfrage, verarbeitet sie und greift bei Bedarf auf das Model zu.
  3. Das Model wird aktualisiert oder Daten werden aus dem Model abgerufen.
  4. Der Controller gibt das Model an die View weiter.
  5. Die View generiert eine HTML-Antwort und sendet sie an den Benutzer.

33.2 Komponenten des MVC-Musters in Spring Boot

33.2.1 1. Controller

Der Controller in Spring Boot verarbeitet HTTP-Anfragen, steuert den Datenfluss zwischen Model und View und steuert, welche View die Daten an den Benutzer präsentiert. In Spring Boot werden Controller mit der Annotation @Controller oder @RestController gekennzeichnet.

33.2.1.1 Beispiel: Einfacher Controller

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {

    @GetMapping("/home")
    public String home(Model model) {
        model.addAttribute("message", "Willkommen bei Spring Boot MVC!");
        return "home"; // Name der View (home.html)
    }
}

In diesem Beispiel empfängt der HomeController eine HTTP-Anfrage auf die URL /home. Er fügt eine Nachricht (message) zum Model hinzu, die an die View weitergegeben wird. Die View home.html wird verwendet, um die Antwort zu generieren.

33.2.2 2. Model

Das Model repräsentiert die Daten, die zwischen dem Controller und der View ausgetauscht werden. In Spring MVC wird das Model durch die Schnittstelle Model repräsentiert, die als Container für die Daten fungiert, die an die View weitergeleitet werden.

33.2.2.1 Beispiel: Daten im Model hinzufügen

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class GreetingController {

    @GetMapping("/greeting")
    public String greeting(Model model) {
        model.addAttribute("name", "John Doe");
        return "greeting";
    }
}

In diesem Beispiel wird das Attribut name dem Model hinzugefügt. Die View greeting.html kann dann auf diese Daten zugreifen und sie in der Benutzeroberfläche darstellen.

33.2.3 3. View

Die View ist verantwortlich für die Darstellung der Daten, die vom Controller bereitgestellt werden. In Spring Boot werden Views typischerweise durch Templates wie Thymeleaf oder andere Template-Engines (z.B. FreeMarker oder JSP) realisiert. Views rendern die HTML-Antwort, die an den Benutzer gesendet wird.

33.2.3.1 Beispiel: Thymeleaf-Template

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Greeting</title>
</head>
<body>
    <h1 th:text="'Hello, ' + ${name} + '!'"></h1>
</body>
</html>

In diesem Beispiel wird die name-Variable, die im Controller dem Model hinzugefügt wurde, in der View greeting.html verwendet, um eine personalisierte Begrüßung zu generieren.

33.3 Verarbeitung von HTTP-Anfragen

In Spring Boot verarbeiten Controller HTTP-Anfragen mithilfe von Annotationen wie @GetMapping, @PostMapping, @PutMapping und @DeleteMapping, die den entsprechenden HTTP-Methoden GET, POST, PUT und DELETE entsprechen.

33.3.1 Beispiel: Verarbeitung einer GET-Anfrage

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class QueryController {

    @GetMapping("/search")
    public String search(@RequestParam("query") String query, Model model) {
        model.addAttribute("result", "Ergebnis für: " + query);
        return "searchResult";
    }
}

In diesem Beispiel empfängt der QueryController eine GET-Anfrage auf /search, liest den Parameter query aus und fügt das Suchergebnis dem Model hinzu. Die View searchResult.html wird verwendet, um das Ergebnis anzuzeigen.

33.3.2 Beispiel: Verarbeitung einer POST-Anfrage

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class FormController {

    @PostMapping("/submitForm")
    public String submitForm(@RequestParam("name") String name, Model model) {
        model.addAttribute("message", "Formular gesendet von: " + name);
        return "formResult";
    }
}

Hier wird eine POST-Anfrage an den Controller gesendet, wenn das Formular abgeschickt wird. Der Controller liest den Parameter name aus und fügt eine Nachricht dem Model hinzu, die in der View formResult.html dargestellt wird.

33.4 Validierung von Benutzereingaben

Spring Boot unterstützt die Validierung von Benutzereingaben mithilfe der Bean-Validation-API und der Annotationen wie @Valid oder @Validated.

33.4.1 Beispiel: Validierung eines Formulars

import javax.validation.constraints.NotEmpty;

public class UserForm {

    @NotEmpty(message = "Der Name darf nicht leer sein")
    private String name;

    // Getter und Setter
}
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

    @GetMapping("/userForm")
    public String showForm(Model model) {
        model.addAttribute("userForm", new UserForm());
        return "userForm";
    }

    @PostMapping("/submitUserForm")
    public String submitForm(@Valid @ModelAttribute("userForm") UserForm userForm, BindingResult result, Model model) {
        if (result.hasErrors()) {
            return "userForm";
        }
        model.addAttribute("message", "Formular erfolgreich gesendet.");
        return "formResult";
    }
}

In diesem Beispiel wird das Formular UserForm validiert. Falls Validierungsfehler auftreten, wird die Eingabemaske erneut angezeigt, andernfalls wird eine Erfolgsnachricht in der View angezeigt.

33.5 Fehlerbehandlung in Spring MVC

Spring Boot bietet Mechanismen zur Fehlerbehandlung in MVC-Anwendungen. Eine Möglichkeit besteht darin, eigene Fehlerseiten zu definieren, die bei bestimmten HTTP-Statuscodes (z.B. 404 oder 500) angezeigt werden.

33.5.1 Beispiel: Fehlerseite für 404-Fehler

<!-- src/main/resources/templates/error/404.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Seite nicht gefunden</title>
</head>
<body>
    <h1>Die angeforderte Seite wurde nicht gefunden!</h1>
</body>
</html>

Spring leitet automatisch auf diese benutzerdefinierte Seite weiter, wenn eine Seite nicht gefunden wird.

33.6 Internationale Unterstützung (i18n)

Spring MVC unterstützt die Internationalisierung (i18n), um Anwendungen in mehreren Sprachen verfügbar zu machen. Dies wird durch das Laden von Lokalisierungsdateien (z.B. messages_de.properties und messages_en.properties) und die Konfiguration von Lokalisierungspräferenzen ermöglicht.

33.6.1 Beispiel: Internationalisierte Nachrichten

messages_en.properties

greeting=Hello, {0}!

messages_de.properties

greeting=Hallo, {0}!

Im Controller:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.Locale;

@Controller
public class GreetingController {

    @Autowired
    private MessageSource messageSource;

    @GetMapping("/i18nGreeting")
    public String greeting(Model model, Locale locale) {
        String message = messageSource.getMessage("greeting", new Object[]{"John"}, locale);
        model.addAttribute("message", message);
        return "greeting";
    }
}

Hier wird die Nachricht in der richtigen Sprache basierend auf den Lokalisierungseinstellungen des Benutzers angezeigt.

33.7 tl;dr

Das MVC-Muster in Spring Boot trennt die Verantwortlichkeiten in Webanwendungen klar und fördert so die Wartbarkeit, Skalierbarkeit und Testbarkeit. Controller verarbeiten Anfragen und interagieren mit Modellen, während Views die Daten dem Benutzer präsentieren. Durch die Nutzung von Spring Boot und Spring MVC können Sie leistungsfähige Webanwendungen mit geringem Entwicklungsaufwand und einer klaren Struktur entwickeln.