Rest Controller mit Spring Boot

Im letzten Tutorial haben wir kennen gelernt wie man mit Spring Boot mit Apache Maven in kürzester Zeit Applikationen erstellen kann. In diesem Tutorial geht es darum einen Rest Controller mit Spring Boot zu erstellen. Wir werden kennen lernen, wie man einen Rest Controller erstellt und wie man unterschiedliche HTTP Methoden (GET, POST) anbietet.
Spring Boot Profile

Spring Boot – RestController mit Spring Boot erstellen

Einleitung

Im letzten Tutorial haben wir kennen gelernt wie man mit Spring Boot und Apache Maven in kürzester Zeit Applikationen erstellen kann. In diesem Tutorial geht es darum einen Rest Controller mit Spring Boot zu erstellen. Wir werden kennen lernen, wie man einen Rest Controller erstellt und wie man unterschiedliche HTTP Methoden (GET, POST) anbietet.

Voraussetzung

Spring Boot RestController Projekt erstellen

Rest Controller sind im Spring Boot Umfeld Java Klassen, die mit speziellen Annotationen angereichert werden. Um eine einfache Java Klasse zu einem Rest Controller zu deklarieren ist es ausreichend, dass die Klasse mit „@RestController“ notiert wird.

RestController aktivieren

Der folgende Codeblock zeigt einen einfachen Rest Controller:

package de.ertantoker.tutorial;

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

@RestController
public class CustomerController {
}

Nun haben wir unseren ersten Rest Controller, leider kann dieser nicht viel machen. Es fehlen noch die HTTP Methoden, die als Rest Schnittstellen genutzt werden können. Spring Boot bietet hier die Möglichkeit Java Methoden mit den entsprechenden Annotationen anzureichern, so dass diese dann als Rest Methoden zur Verfügung stehen.

Als Beispiel werden wir den CustomerController nun so erweitern, dass wir jeweils die HTTP Methoden GET und POST implementieren werden!

Im Rest Kontext werden GET Methoden für Schnittstellen genutzt, die eine Ressource zurückgeben. In unserem Fall werden wir zwei GET Methoden implementieren. Die erste GET Methode wird uns alle Kunden als JSON Liste zurück geben. Die zweite GET Methode wird uns genau einen Kunden zurück geben. Hierbei werden wir den Kunden nach seiner ID suchen und zurück geben. In diesem Tutorial wird absichtlich keine SQL oder NoSQL Datenbank genutzt, damit der Fokus auf den Kontext Rest erhalten bleibt.

RequestMapping definieren

Damit ein Rest Controller überhaupt auf HTTP Anfragen reagieren kann, ist es zwingend erforderlich dem Rest Controller mitzuteilen unter welcher URL er angesprochen werden kann. Hierfür muss man den Rest Controller um die Annotation „@RequestMapping“ erweitern. In unserem Fall erweitern wir den CustomerController der über die URL http://localhost:8080/customers erreichbar sein soll.

package de.ertantoker.tutorial;

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

@RestController
@RequestMapping("/customers")
public class CustomerController {
}

Get Methode für das Holen von Objektlisten

Nun ist unser Rest Controller zwar um einen URL Mapping reicher, aber auf HTTP Methoden kann er immer noch nicht reagieren! Um die erste GET Methode zu implementieren benötigen wir eine Java Methode, die uns als Rückgabewert eine Liste von Kunden zurück gibt. Diese Methode müssen wir um die Annotation „@GetMapping“ erweitern. Per Default ist es so, das das GetMapping ohne eine URL Angabe das Mapping aus der Klasse übernimmt. Dies bedeutet wenn wir eine Methode mit @GetMapping erweitern, dass diese dann unter der URL http://localhost:8080/customers erreichbar ist. Der Annotation @GetMapping kann als Parameter ein String übergeben werden, wo dann noch weitere spezielle URL Angaben wie Path Variablen definiert werden können. In unserem Fall reicht aber ein einfaches @GetMapping aus. In der zweiten GET Methode werde ich dann darauf eingehen, wie man Path Variablen definiert.

Get Methode implementieren

package de.ertantoker.tutorial;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/customers")
public class CustomerController {

    @GetMapping
    public ResponseEntity<List<Customer>> getCustomers() {
        return null;
    }
}

Wir haben jetzt eine GET Methode, die per Schnittstellen Definition uns eine Liste von Kunden zurück gibt, aber uns fehlt noch die Implementierung. Testweise werden wir dann jetzt hier Kunden Objekte zurück geben, die wir in einer statischen Liste „speichern“ werden. Diese Implementierung ist bewusst gewählt, da diese später abgeändert wird.

Folgender Codeblock zeigt eine einfache Implementierung mit der statischen Liste.

package de.ertantoker.tutorial;

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

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

@RestController
@RequestMapping("/customers")
public class CustomerController {

    private static Integer customerId = 0;
    private static List<Customer> customers = new ArrayList<>();

    @GetMapping
    public ResponseEntity<List<Customer>> getCustomers() {

        Customer customer = new Customer();
        customer.setId(String.valueOf(customerId++));
        customer.setFirstname("Firstname " + customerId);
        customer.setLastname("Lastname " + customerId);

        customers.add(customer);

        return new ResponseEntity<>(customers, HttpStatus.OK);
    }
}

Ihr werdet euch beim Inspizieren des Codeblockes bestimmt gefragt haben, was die Return Zeile der Methode getCustomers() macht. Hier sehen wir, dass nicht direkt eine Liste von Kunden zurück gegeben wird, sondern ein ResponseEntity Objekt, welches eine Liste von Kunden und den HTTP Status OK beinhaltet. Durch den Rückgabewert über einen ResponseEntity ist es möglich im Quellcode unterschiedliche HTTP Status zurück zu geben. Bei GET Methoden die abhängig von Request oder Path Parametern Daten suchen müssen, kann man so im Falle eines nicht finden eines Ergebnisses ein ResponseEntity mit dem HTTP Status NOT_FOUND zurück geben. Dazu aber später mehr in der zweiten GET Methode.

Post Methode testen

Wenn wir jetzt über Postman unseren RestController über die URL GET http://localhost:8080/customers aufrufen, so sehen wir dass uns eine Liste von Kunden zurück gegeben wird. Der HTTP Status ist in diesem Fall OK. Beim zweiten Aufruf würden wir dann einen zweiten Kunden zusätzlich in der Liste haben.

Spring Boot Rest Controller

Post Methode für das Anlegen eines Objektes

Nun haben wir unsere erste GET Methode für unseren RestController implementiert. Jetzt sollten wir unseren RestController so erweitern, dass wir neue Kunden über die Rest Schnittstelle anlegen können. Auch hier dient die statische Liste als Datenbankersatz. Um über Rest Schnittstellen Ressourcen oder Objekte anzulegen benötigen wir eine POST Methode, die im Request Body das zu anlegende Objekt beinhaltet. In unseren Fall ist es ein neuer Kunde den wir anlegen wollen.

Post Methode implementieren

Wie schon erwähnt, brauchen wir eine POST Methode. Hierfür müssen wir eine Java Methode erweitern bzw anlegen mit der Annotation „@PostMapping“. Wie beim GetMapping werden wir auch hier keine spezielle URL Definition als Parameter der PostMapping Annotation übergeben. In diesem Fall wird ebenfalls das Mapping aus der Klasse übernommen. Als Rückgabewert werden wir das Objekt, welches wir über  Post Methode angelegt haben, wieder zurück geben. Das Objekt wird beim Anlegen mit einer ID angereichert und dann zurück gegeben.

package de.ertantoker.tutorial;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

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

@RestController
@RequestMapping("/customers")
public class CustomerController {

    private static Integer customerId = 0;
    private static List<Customer> customers = new ArrayList<>();

    @GetMapping
    public ResponseEntity<List<Customer>> getCustomers() {
        return new ResponseEntity<>(customers, HttpStatus.OK);
    }

    @PostMapping
    public ResponseEntity<Customer> createCustomer(@RequestBody Customer customer) {
        customer.setId(String.valueOf(customerId++));
        customers.add(customer);
        return new ResponseEntity<>(customer, HttpStatus.CREATED);
    }
}

Post Methode testen

Beim Aufruf der URL GET http://localhost:8080/customers  erhalten wir eine leere Liste. Es wird empfohlen bei GET Methoden die eine Liste als Rückgabewert haben, stets eine leere Liste zurück zugeben anstatt ein NULL oder einen HTTP STATUS NOT_FOUND.

Nun rufen wir die Post Methode unseres CustomerController mit einem RequestBody, welches unsere Kundendaten beinhaltet auf. Unser Body besteht aus einem einfachen JSON Objekt ,welches jeweils einen firstname und ein lastname Atribut beinhaltet.

Wir sehen nun, dass unser Kunde Albert Einstein angelegt wurde. Der Aufruf der POST Methode liefert uns im Status CREATED zurück und als Rückgabewert einen Kunden Objekt mit einer ID. Nun können wir ruhig mehrere Aufrufe gegen die POST Methode starten. Bei jedem Aufruf wird ein neuer Kunde angelegt und in der statischen Liste gespeichert.

Nach dem Speichern des ersten Kunden können wir wieder unsere erste GET Methode aufrufen, die uns alle gespeicherten Kunden als Liste zurück gibt.

Get Methode für das Holen von einem Object

Jetzt fehlt uns nur noch die zweite GET Methode, mit der wir speziell nach einzelnen Kunden suchen können. Hierfür werden wir eine neue GET Methode implementieren, die uns nach dem folgenden URL Schema Kunden zurück gibt.

Beispiel: http://localhost:8080/customers/0 -> liefert den Kunden mit der ID 0
Beispiel: http://localhost:8080/customers/1 -> liefert den Kunden mit der ID 1

Get Methode implementieren

Unsere GET URL hat folgendes Schema http://localhost:8080/customers/{id}
Wir sehen, dass wir hier eine Path Variable benötigen. Wie schon weiter oben im Tutorial erwähnt kann man mit Spring Boot und den Mapping Annotationen die URL’s der Methoden weiter spezifizieren. Für die zweite GET Methode brauchen wir eine weitere Java Methode mit dem Rückgabewert ResponseEntity<Customer> und einem @GetMapping(„/{id}“).

package de.ertantoker.tutorial;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

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

@RestController
@RequestMapping("/customers")
public class CustomerController {

    private static Integer customerId = 0;
    private static List<Customer> customers = new ArrayList<>();

    @GetMapping
    public ResponseEntity<List<Customer>> getCustomers() {
        return new ResponseEntity<>(customers, HttpStatus.OK);
    }

    @PostMapping
    public ResponseEntity<Customer> createCustomer(@RequestBody Customer customer) {
        customer.setId(String.valueOf(customerId++));
        customers.add(customer);
        return new ResponseEntity<>(customer, HttpStatus.CREATED);
    }

    @GetMapping("/{id}")
    public ResponseEntity<Customer> getCustomerById(@PathVariable String id) {
        return customers.stream()
                .filter(customer -> customer.getId().equals(id))
                .findFirst()
                .map(customer -> new ResponseEntity<>(customer, HttpStatus.OK))
                .orElseGet(() -> new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }
}

Nun ist die Implementierung für die GET Methode abgeschlossen. Auf die konkrete Java 8 Implementierung der Methode werde ich jetzt nicht im Detail eingehen. Das würde hier den Rahmen des Tutorials sprengen. Kurz gesagt in der statischen Liste wird nach dem Kunden gesucht mit der entsprechenden ID. Falls dieser gefunden wird, wird der Kunde im ResponseEntity Object zurück gegeben. Falls kein Kunde mit der ID gefunden wird, wird ein ResponseEntity mit dem HTTP Status NOT_FOUND zurück gegeben.

Somit wären wir mit der Implementierung des Rest Controller fertig. Natürlich kann man den Rest Controller um weitere Methoden erweitern. Im nächsten Tutorial wird es darum gehen, dass wir die Daten über eine Respository Klasse direkt in eine MongoDB abspeichern und auch diese von dort wieder laden.

Das Ergebnis

Ich hoffe euch hat dieses Tutorial gefallen. Solltet ihr Fragen, Kritik und Anregungen haben dann könnt ihr gerne diese als Kommentar schreiben.

[amazon_link asins=’3864905257,3864901200,3864903874′ template=’ProductGrid‘ store=’fitnes06-21′ marketplace=’DE‘ link_id=’291d18c2-b4f5-11e8-8879-b9f57c76800b‘]

Verwandte Beiträge

Comments (5)

Vielen herzlichen Dank!

Als Sprint Neuling habe ich die letzten 3 Tage damit verbracht irgendwo ein solches Tutorial und überall nur entweder veraltete Anleitungen gefunden oder Tutorials die an Fortgeschrittene Sprint Anwender gerichtet waren.
Du schaffst auf wahnsinnig gute Weise den Spagat zwischen Neulinge abholen und gleichzeitig eine doch schon recht spezifische Thematik beibringen.

Damit der Code funktioniert, muss noch eine Customer-Klasse erstellt werden, oder?
Kannst du darauf eingehen, was in der noch alles enthalten sein muss, damit die App funktioniert?
Ich habe das Gefühl, dass zwischen dem letzten und diesem Tutorial eine Lücke ist, und weiß selbst nicht, wie ich die
füllen muss, damit die Anwendung läuft…

Hallo RR du hast vollkommen Recht. Da fehlt die Customer.java Klasse.

Diese muss folgende Properties haben

Id, firstname und lastname. Alle von Typ String.

Vielen Dank für dein Kommentar.

Hallo,
da müssen doch auch die getter und setter Methoden in die Customer Klasse erstellt werden oder?

Hallo, ja die Customer Klasse fehlt komplett in dem Beispiel. Ich bin davon ausgegangen, dass es selbstverständlich ist. Wie in dem Kommentar vorher erwähnt muss diese vorhanden sein und auch die Setter und die Getter müssen vorhanden sein.

Spring Boot (Jackson) braucht für jedes Objekt welches serialisieren und deserialisieren will einen default Konstruktor und die Setter und die Getter.

Leave a comment