38 Spring Boot Rest Controller

In Spring Boot ist der RestController eine spezielle Art von Controller, der für die Entwicklung von RESTful Webservices verwendet wird. Ein RESTful Webservice ist eine Webanwendung, die HTTP-Methoden (GET, POST, PUT, DELETE) verwendet, um auf Ressourcen zuzugreifen und sie zu verwalten. Der @RestController kombiniert die Funktionalitäten von @Controller und @ResponseBody, wodurch es möglich ist, HTTP-Antworten direkt als JSON oder XML zu senden, ohne dass eine zusätzliche View-Schicht erforderlich ist.

In diesem Kapitel gehen wir auf die Verwendung von @RestController in Spring Boot ein, erläutern den Unterschied zu @Controller, zeigen Beispiele und beleuchten bewährte Methoden.

38.1 Überblick über @RestController

38.1.1 Was ist @RestController?

@RestController ist eine spezielle Annotation in Spring, die auf Klassen angewendet wird, um sie als REST-Endpunkte zu kennzeichnen. Sie dient als Vereinfachung für @Controller in Kombination mit @ResponseBody, was bedeutet, dass alle Methoden in dieser Klasse direkt die HTTP-Antwort als JSON (oder ein anderes Format) zurückgeben, anstatt eine View zu rendern.

38.1.1.1 Beispiel: Einfache @RestController-Klasse

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

@RestController
public class ProductController {

    @GetMapping("/products")
    public List<Product> getAllProducts() {
        return productService.getAllProducts();
    }
}

In diesem Beispiel gibt der @RestController die Liste der Produkte als JSON zurück, wenn die URL /products aufgerufen wird. Es wird keine View gerendert; die Antwort wird direkt als JSON generiert.

38.1.2 Unterschied zwischen @Controller und @RestController

@RestController ist im Wesentlichen eine Kombination aus @Controller und @ResponseBody, was bedeutet, dass bei jeder Methode automatisch @ResponseBody angewendet wird, um die Rückgabe als HTTP-Antwort zu serialisieren.

// Äquivalent zu @RestController
@Controller
@ResponseBody
public class ProductController {
    @GetMapping("/products")
    public List<Product> getAllProducts() {
        return productService.getAllProducts();
    }
}

38.2 HTTP-Antworten in einem @RestController

Ein @RestController bietet verschiedene Möglichkeiten, um HTTP-Antworten zurückzugeben. Standardmäßig serialisiert Spring Boot die zurückgegebenen Java-Objekte automatisch als JSON oder XML.

38.2.1 1. Rückgabe von Java-Objekten

Spring Boot serialisiert Java-Objekte automatisch in JSON, wenn sie von einem @RestController zurückgegeben werden. Dies geschieht mit der Jackson-Bibliothek, die in Spring Boot standardmäßig eingebunden ist.

38.2.1.1 Beispiel: Rückgabe eines Produkts als JSON

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 Product getProductById(@PathVariable Long id) {
        return productService.getProductById(id);
    }
}

Hier wird die getProductById()-Methode aufgerufen, wenn die URL /products/{id} abgerufen wird. Spring Boot serialisiert das Product-Objekt automatisch in JSON.

38.2.2 2. Verwendung von ResponseEntity

ResponseEntity bietet mehr Kontrolle über die HTTP-Antwort, z.B. über Statuscodes, Header und den Antwortkörper. Dies ist besonders nützlich, wenn Sie spezifische Statuscodes wie 404 Not Found oder 500 Internal Server Error zurückgeben möchten.

38.2.2.1 Beispiel: Verwendung von ResponseEntity

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 ResponseEntity.ok(product); // Status 200 OK
        } else {
            return ResponseEntity.notFound().build(); // Status 404 Not Found
        }
    }
}

In diesem Beispiel wird eine ResponseEntity mit dem Statuscode 200 OK zurückgegeben, wenn das Produkt gefunden wird. Andernfalls wird eine leere Antwort mit dem Status 404 Not Found zurückgegeben.

38.2.3 3. Rückgabe von HTTP-Statuscodes

Zusätzlich zu ResponseEntity können Sie mit den Annotationen @ResponseStatus HTTP-Statuscodes direkt in der Methode festlegen.

38.2.3.1 Beispiel: Rückgabe eines Statuscodes mit @ResponseStatus

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProductController {

    @GetMapping("/products")
    @ResponseStatus(HttpStatus.OK)
    public List<Product> getAllProducts() {
        return productService.getAllProducts();
    }
}

In diesem Beispiel wird der Statuscode 200 OK explizit mit der Annotation @ResponseStatus gesetzt.

38.3 Arbeiten mit Path- und Request-Parametern

In einem @RestController können Sie sowohl Path-Parameter als auch Query-Parameter verarbeiten. Path-Parameter werden direkt in der URL definiert, während Query-Parameter optional über die URL übergeben werden.

38.3.1 1. Verwendung von Path-Parametern

Path-Parameter werden mit der Annotation @PathVariable verarbeitet. Sie sind nützlich, wenn Sie eine Ressource anhand einer eindeutigen ID oder eines anderen Attributs abrufen möchten.

38.3.1.1 Beispiel: Path-Parameter

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 Product getProductById(@PathVariable Long id) {
        return productService.getProductById(id);
    }
}

In diesem Beispiel wird der Wert {id} in der URL /products/{id} als Path-Parameter verwendet, um das entsprechende Produkt zu identifizieren.

38.3.2 2. Verwendung von Query-Parametern

Query-Parameter werden mit der Annotation @RequestParam verarbeitet. Diese Parameter sind optional und werden in der URL nach einem ? eingefügt.

38.3.2.1 Beispiel: Query-Parameter

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

@RestController
public class ProductController {

    @GetMapping("/products")
    public List<Product> getProductsByCategory(@RequestParam(required = false) String category) {
        if (category != null) {
            return productService.getProductsByCategory(category);
        } else {
            return productService.getAllProducts();
        }
    }
}

In diesem Beispiel wird der Query-Parameter category optional übergeben. Wenn der Parameter vorhanden ist, werden nur Produkte der angegebenen Kategorie zurückgegeben.

38.4 Exception Handling in @RestController

In einer REST-API ist es wichtig, Fehler und Ausnahmen angemessen zu behandeln. Spring Boot bietet Mechanismen zum globalen und lokalen Exception-Handling.

38.4.1 1. Globale Ausnahmebehandlung mit @ControllerAdvice

Mit @ControllerAdvice können Sie Ausnahmen, die in einem @RestController auftreten, global behandeln.

38.4.1.1 Beispiel: Globale Fehlerbehandlung

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ProductNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public String handleProductNotFound(ProductNotFoundException ex) {
        return ex.getMessage();
    }
}

Hier wird eine benutzerdefinierte Ausnahme ProductNotFoundException global behandelt. Wenn die Ausnahme auftritt, wird eine 404 Not Found-Antwort zurückgegeben.

38.4.2 2. Lokales Exception-Handling mit @ExceptionHandler

Sie können auch spezifische Ausnahmen lokal innerhalb eines Controllers behandeln.

38.4.2.1 Beispiel: Lokale Fehlerbehandlung

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
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 Product getProductById(@PathVariable Long id) {
        return productService.getProductById(id)
               .orElseThrow(() -> new ProductNotFoundException("Produkt nicht gefunden"));
    }

    @ExceptionHandler(ProductNotFoundException.class)
    public ResponseEntity<String> handleProductNotFound(ProductNotFoundException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body

(ex.getMessage());
    }
}

In diesem Beispiel wird die Ausnahme ProductNotFoundException lokal innerhalb des ProductController behandelt.

38.5 tl;dr

Der @RestController in Spring Boot ist das Herzstück jeder REST-API. Er ermöglicht es Entwicklern, HTTP-Anfragen auf einfache Weise zu verarbeiten und direkt JSON-Antworten zurückzugeben. Durch die Kombination von Path- und Query-Parametern, die Verwendung von ResponseEntity zur genauen Steuerung der HTTP-Antworten und das effiziente Exception Handling bietet Spring Boot eine leistungsfähige Plattform zur Entwicklung von RESTful Webservices.