Читать книгу Spring Boot - Mark Heckler - Страница 36

Los geht's mit »GET«

Оглавление

REST-APIs befassen sich mit Objekten, und Objekte können allein oder als Gruppe verwandter Objekte auftreten. Nehmen wir unser Kaffee-Szenario. Sie könnten sich z.B. einen bestimmten Kaffee holen wollen. Oder Sie wollen alle Kaffees haben, alle dunklen Röstungen, alle, die in einen bestimmten Bereich von Identifikatoren fallen, oder die »kolumbianisch« in ihrer Beschreibung führen. Um es zu ermöglichen, eine Instanz oder mehr als eine Instanz eines Objekts zu beziehen, bietet es sich an, mehrere Methoden in unserem Code anzulegen.

Ich beginne mit dem Erzeugen einer Liste von Coffee-Objekten, um die Methode zu unterstützen, die mehrere Coffee-Objekte zurückliefert, wie in der folgenden rudimentären Klassendefinition zu sehen. Ich definiere die Variable, die diese Gruppe von Kaffees enthält, als List von Coffee-Objekten. Ich wähle List als abstraktere Schnittstelle für meinen Member-Variablentyp, weise aber eigentlich eine leere ArrayList zur Verwendung in der RestApiDemoController-Klasse zu:

@RestController

class RestApiDemoController {

private List<Coffee> coffees = new ArrayList<>();

}

Empfehlenswert ist, den höchstmöglichen Typ (Klasse, Schnittstelle) zu übernehmen, der sauber die internen und externen APIs bedient. Diese müssen nicht in allen Fällen passen, wie sie es ja auch hier nicht tun. Intern bietet List mir das Maß an API, das es mir erlaubt, auf Basis meiner Kriterien die sauberste Implementierung herzustellen; extern können wir eine sogar noch höhere Abstraktion definieren, wie ich in Kürze demonstrieren werde.

Es ist immer eine gute Idee, einige Daten zum Abrufen zu haben, um sicherzugehen, dass alles so funktioniert, wie es soll. Im folgenden Code erzeuge ich einen Konstruktor für die Klasse RestApiDemoController, um Code hinzuzufügen, der die Liste der Kaffeesorten bei der Objekterzeugung füllt:

@RestController

class RestApiDemoController {

private List<Coffee> coffees = new ArrayList<>();

public RestApiDemoController() {

coffees.addAll(List.of(

new Coffee("Café Cereza"),

new Coffee("Café Ganador"),

new Coffee("Café Lareño"),

new Coffee("Café Três Pontas")

));

}

}

Wie im folgenden Code gezeigt, erzeuge ich eine Methode in der Klasse RestApiDemo Controller, die eine iterierbare Gruppe von Kaffees zurückliefert, die durch unsere Member-Variable coffees repräsentiert wird. Ich entscheide mich für ein Iterable <Coffee>, weil jeder iterierbare Typ die gewünschte Funktionalität dieses API zufriedenstellend bietet. Ich setzte @RequestMapping ein, um mit GET die Liste der Kaffees abzurufen.

@RestController

class RestApiDemoController {

private List<Coffee> coffees = new ArrayList<>();

public RestApiDemoController() {

coffees.addAll(List.of(

new Coffee("Café Cereza"),

new Coffee("Café Ganador"),

new Coffee("Café Lareño"),

new Coffee("Café Três Pontas")

));

}

@RequestMapping(value = "/coffees", method = RequestMethod.GET)

Iterable<Coffee> getCoffees() {

return coffees;

}

}

Zur @RequestMapping-Annotation füge ich die Pfadangabe /coffees und die Methode vom Typ RequestMethod.GET hinzu. Das bedeutet, dass die Methode auf Anfragen mit dem Pfad /coffees antwortet und Anfragen auf HTTP GET-Requests beschränkt. Diese Methode erledigt das Beziehen von Daten, aber keine Aktualisierungen irgendeiner Art. Spring Boot führt über die Jackson-Abhängigkeiten, die in Spring Web enthalten sind, das Marshalling und Demarshalling von Objekten in JSON und andere Formate automatisch aus.

Wir können dies mit einer weiteren Convenience-Annotation weiter rationalisieren. Wenn Sie @GetMapping verwenden, geben Sie im Prinzip die Anweisung, nur GET-Anfragen zuzulassen, Sie reduzieren den Überhang und verlangen lediglich eine Pfadangabe. Es wird sogar path = weggelassen, da keine Konfliktvermeidung bei den Parametern erforderlich ist. Der folgende Code demonstriert, wie sich die Lesbarkeit des Codes verbessert, wenn Sie diese Annotation verwenden:

@GetMapping("/coffees")

Iterable<Coffee> getCoffees() {

return coffees;

}

Hilfreiche Hinweise zu @RequestMapping

@RequestMapping besitzt mehrere spezielle Convenience-Annotationen:

 @GetMapping

 @PostMapping

 @PutMapping

 @PatchMapping

 @DeleteMapping

All diese Mapping-Annotationen können auf Klassen- oder Methodenebene angewandt werden, und Pfade sind zusätzlich. Würde ich z.B. den RestApiDemoController und seine getCoffees()-Methode annotieren, wie im folgenden Code gezeigt, dann würde die Anwendung genauso reagieren wie mit dem Code, der in den vorherigen zwei Codeausschnitten gezeigt wurde:

@RestController

@RequestMapping("/")

class RestApiDemoController {

private List<Coffee> coffees = new ArrayList<>();

public RestApiDemoController() {

coffees.addAll(List.of(

new Coffee("Café Cereza"),

new Coffee("Café Ganador"),

new Coffee("Café Lareño"),

new Coffee("Café Três Pontas")

));

}

@GetMapping("/coffees")

Iterable<Coffee> getCoffees() {

return coffees;

}

}

Das Beziehen aller Kaffees aus unserem provisorischen Datenspeicher ist ganz gut, reicht aber nicht. Was ist, wenn wir einen ganz bestimmten Kaffee haben wollen?

Das Beziehen eines einzelnen Elements funktioniert so ähnlich wie das Beziehen mehrerer Elemente. Ich füge eine weitere Methode namens getCoffeeById hinzu, um das für uns zu erreichen. Sie sehen das im nächsten Codeausschnitt.

Der {id}-Teil des angegebenen Pfads ist eine URI-(Uniform-Resource-Identifier-) Variable. Sein Wert wird über den id-Methodenparameter an die Methode get CoffeeById übergeben, indem sie mit @PathVariable annotiert wird.

Durch ein Iterieren über die Liste der Kaffees gibt die Methode ein gefülltes Optional <Coffee> zurück, falls sie einen Treffer findet, ansonsten gibt sie ein leeres Optional <Coffee> zurück (falls die angeforderte id in unserer kleinen Gruppe aus Kaffees nicht vorhanden ist):

@GetMapping("/coffees/{id}")

Optional<Coffee> getCoffeeById(@PathVariable String id) {

for (Coffee c: coffees) {

if (c.getId().equals(id)) {

return Optional.of(c);

}

}

return Optional.empty();

}

Spring Boot

Подняться наверх