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
- Existierende Java 8 Installation
- Existierende Maven 3 Installation
- Grundkenntnisse in REST
- Tutorial: Spring Boot Projekte mit Maven
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.
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‘]