41 Spring MVC und REST

Spring MVC (Model-View-Controller) ist eines der Kernmodule des Spring Frameworks und bildet die Grundlage für die Entwicklung von Webanwendungen. In der Welt von RESTful Webservices ist Spring MVC ein leistungsfähiges Framework zur Handhabung von HTTP-Anfragen und -Antworten. Es bietet eine robuste Infrastruktur, um RESTful APIs zu erstellen, wobei Daten in JSON oder XML zwischen Client und Server ausgetauscht werden.

In diesem Kapitel betrachten wir die Beziehung zwischen Spring MVC und REST, wie REST-Architekturen mit Spring MVC aufgebaut werden, und die Unterschiede zwischen traditionellen MVC-Webanwendungen und RESTful Webservices.

41.1 Spring MVC: Überblick

41.1.1 MVC-Architektur

In einer traditionellen MVC-Architektur wird eine Webanwendung in drei Komponenten unterteilt:

  1. Model: Repräsentiert die Daten und Geschäftslogik der Anwendung.
  2. View: Stellt die Benutzeroberfläche dar, z.B. HTML-Seiten.
  3. Controller: Vermittelt zwischen Model und View. Es verarbeitet Benutzeranfragen, ruft die entsprechenden Daten aus dem Model ab und liefert diese an die View.

Die traditionelle Spring MVC-Webanwendung verwendet HTML-Seiten als View, um die Antwort an den Client zu senden. Dies ist jedoch in RESTful APIs nicht der Fall, da REST-APIs typischerweise JSON oder XML als Antwort senden.

41.1.2 Spring MVC und REST

REST (Representational State Transfer) ist ein Architekturstil, der auf den Prinzipien von HTTP aufbaut. Eine REST-API verwendet HTTP-Methoden wie GET, POST, PUT und DELETE, um CRUD-Operationen (Create, Read, Update, Delete) auf Ressourcen auszuführen. In RESTful Webservices gibt es keine Views wie in traditionellen MVC-Anwendungen. Stattdessen besteht die Kommunikation zwischen Client und Server aus reinen Datenformaten wie JSON oder XML.

41.1.3 Schlüsselkonzepte von REST in Spring MVC

  1. Ressourcen: Jede Entität oder Sammlung von Daten wird als Ressource betrachtet und über eindeutige URLs adressiert.
  2. HTTP-Methoden: GET, POST, PUT, DELETE werden verwendet, um Aktionen auf Ressourcen auszuführen.
  3. Statelessness: Der Server speichert keinen Zustand über den Client. Jede Anfrage enthält alle Informationen, die zur Verarbeitung erforderlich sind.
  4. Repräsentationen: Ressourcen können in verschiedenen Formaten wie JSON oder XML zurückgegeben werden.

41.2 Unterschiede zwischen MVC und REST in Spring

41.2.1 1. Antworten

In Spring MVC-Webanwendungen erfolgt die Antwort über eine View (z.B. JSP, Thymeleaf), die eine HTML-Seite an den Client rendert. In einer RESTful Webanwendung liefert der Controller jedoch typischerweise JSON oder XML, ohne eine View zu rendern.

41.2.1.1 MVC-Webanwendung:

@Controller
public class UserController {
    
    @GetMapping("/users")
    public String showUserList(Model model) {
        List<User> users = userService.getAllUsers();
        model.addAttribute("users", users);
        return "userList"; // Gibt eine HTML-Seite zurück
    }
}

41.2.1.2 RESTful Webservice:

@RestController
public class UserController {

    @GetMapping("/users")
    public List<User> getAllUsers() {
        return userService.getAllUsers(); // Gibt eine JSON-Liste der Benutzer zurück
    }
}

41.2.2 2. Verwendung von @RestController

In Spring MVC-Webanwendungen verwenden wir die Annotation @Controller, um eine Controller-Klasse zu definieren, die Anfragen verarbeitet und Views zurückgibt. Bei RESTful Webservices wird jedoch @RestController verwendet, was implizit @ResponseBody auf alle Methoden anwendet und die Antwort automatisch als JSON oder XML serialisiert.

41.2.2.1 Beispiel: Verwendung von @RestController

@RestController
public class ProductController {

    @GetMapping("/products")
    public List<Product> getAllProducts() {
        return productService.getAllProducts(); // Gibt Produkte als JSON zurück
    }
}

41.2.3 3. Datenformate

Während Spring MVC-Webanwendungen HTML als Hauptdatenformat verwenden, setzen RESTful APIs auf datenfokussierte Formate wie JSON und XML. Spring Boot verwendet Jackson (für JSON) und JAXB (für XML) zur automatischen Serialisierung und Deserialisierung von Java-Objekten.

41.2.3.1 Beispiel: JSON-Antwort in REST

@RestController
public class ProductController {

    @GetMapping("/products/{id}")
    public Product getProductById(@PathVariable Long id) {
        return productService.getProductById(id); // Antwort im JSON-Format
    }
}

Die Antwort wird als JSON zurückgegeben:

{
  "id": 1,
  "name": "Laptop",
  "price": 1200.00
}

41.2.4 4. HTTP-Statuscodes

In traditionellen MVC-Anwendungen sind HTTP-Statuscodes oft implizit (z.B. 200 OK, wenn die Seite erfolgreich geladen wurde). In RESTful APIs spielen HTTP-Statuscodes jedoch eine entscheidende Rolle, um den Status der Anfrage zu kommunizieren.

41.2.4.1 Beispiel: Rückgabe von HTTP-Statuscodes in REST

import org.springframework.http.HttpStatus;
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.RestController;

@RestController
public class ProductController {

    @GetMapping("/products/{id}")
    public ResponseEntity<Product> getProductById(@PathVariable Long id) {
        Product product = productService.getProductById(id);
        if (product != null) {
            return new ResponseEntity<>(product, HttpStatus.OK); // Status 200 OK
        } else {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND); // Status 404 Not Found
        }
    }
}

41.2.5 5. Routen und Endpunkte

In Spring MVC verwenden wir oft eine Mischung aus GET- und POST-Methoden, um Formulare zu verarbeiten und Daten anzuzeigen. In RESTful APIs gibt es jedoch eine klarere Trennung der HTTP-Methoden zur Durchführung spezifischer CRUD-Operationen.

41.2.5.1 CRUD-Operationen in REST

Operation HTTP-Methode Endpunkt Beschreibung
Create POST /products Erstellt eine neue Ressource
Read GET /products Holt eine Liste aller Produkte
Read (One) GET /products/{id} Holt ein spezifisches Produkt
Update PUT /products/{id} Aktualisiert eine Ressource
Delete DELETE /products/{id} Löscht eine Ressource

Diese konsistente Struktur ermöglicht es, RESTful APIs leichter zu verstehen und zu verwenden, da sie auf den HTTP-Methoden basieren.

41.3 RESTful Prinzipien in Spring MVC

41.3.1 1. Statelessness (Zustandslosigkeit)

RESTful Webservices sind zustandslos. Das bedeutet, dass jede Anfrage unabhängig von vorherigen Anfragen verarbeitet wird, und der Server keine Informationen über frühere Anfragen speichert. In Spring Boot wird dies durch die Verwendung von HTTP-Methoden und eindeutigen URLs für jede Ressource umgesetzt.

41.3.2 2. Ressourcenbasierte URLs

In einer REST-API werden Ressourcen durch eindeutige URLs identifiziert. Jede Ressource hat eine eigene URL, und HTTP-Methoden (GET, POST, PUT, DELETE) werden verwendet, um Operationen auf diesen Ressourcen durchzuführen.

41.3.3 3. Trennung von Client und Server

In einer REST-API sind Client und Server unabhängig voneinander. Der Client sendet Anfragen und erwartet eine Antwort in Form von Daten, z.B. JSON. Die serverseitige Implementierung ist dem Client dabei unbekannt, was die Flexibilität erhöht.

41.3.4 4. Hypermedia as the Engine of Application State (HATEOAS)

HATEOAS ist ein wichtiger Aspekt von RESTful APIs, bei dem der Server nicht nur die Daten zurückgibt, sondern auch Links zu verwandten Ressourcen bereitstellt. Dies verbessert die Navigation durch die API und macht den Client flexibler gegenüber Änderungen auf dem Server.

41.4 Fazit

Spring MVC bildet die Grundlage für die Entwicklung von RESTful Webservices in Spring Boot. Während traditionelle MVC-Webanwendungen auf die Trennung von Model, View und Controller setzen, konzentrieren sich RESTful Webservices auf die Bereitstellung von Daten über HTTP. Die Verwendung von @RestController, konsistenten HTTP-Methoden und einer klaren Ressourcenstruktur ermöglicht die einfache und effektive Implementierung von REST-APIs. Die Fähigkeit von Spring Boot, automatisch Java-Objekte in JSON zu serialisieren, erleichtert die Arbeit mit modernen Webanwendungen erheblich.