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

Und mehr

Оглавление

Auch wenn man sicher noch mehr machen könnte, um dieses Szenario zu verbessern, möchte ich mich auf zwei Dinge im Speziellen konzentrieren: das Reduzieren von Wiederholungen und das Zurückliefern von HTTP-Statuscodes, wo das von der Spezifikation verlangt wird.

Um Wiederholungen im Code zu reduzieren, befördere ich den Teil der URI-Zuordnung, der allen Methoden in der RestApiDemoController-Klasse gemeinsam ist, auf die klassenbasierte @RequestMapping-Annotation, "/coffees". Wir können dann diesen Teil des URI aus der Angabe der URI-Zuordnung der einzelnen Methoden entfernen, wodurch sich das textliche »Rauschen« in unserem Code ein wenig verringert, wie der folgende Code zeigt:

@RestController

@RequestMapping("/coffees")

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

Iterable<Coffee> getCoffees() {

return coffees;

}

@GetMapping("/{id}")

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

for (Coffee c: coffees) {

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

return Optional.of(c);

}

}

return Optional.empty();

}

@PostMapping

Coffee postCoffee(@RequestBody Coffee coffee) {

coffees.add(coffee);

return coffee;

}

@PutMapping("/{id}")

Coffee putCoffee(@PathVariable String id, @RequestBody Coffee coffee) {

int coffeeIndex = -1;

for (Coffee c: coffees) {

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

coffeeIndex = coffees.indexOf(c);

coffees.set(coffeeIndex, coffee);

}

}

return (coffeeIndex == -1) ? postCoffee(coffee) : coffee;

}

@DeleteMapping("/{id}")

void deleteCoffee(@PathVariable String id) {

coffees.removeIf(c -> c.getId().equals(id));

}

}

Anschließend schaue ich in das bereits erwähnte IETF-Dokument und stelle fest, dass HTTP-Statuscodes zwar für GET nicht angegeben sind und für die Methoden POST und DELETE nur empfohlen werden, sie aber für Antworten der PUT-Methode erforderlich sind. Um das zu erreichen, ändere ich die Methode putCoffee so, wie im folgenden Codesegment gezeigt. Anstatt nur das aktualisierte oder erzeugte Coffee-Objekt zurückzuliefern, liefert die Methode putCoffee nun eine Response Entity zurück, die besagten Coffee sowie den passenden HTTP-Statuscode enthält: 201 (Created), falls der mit PUT zu aktualisierende Kaffee noch nicht existierte, und 200 (OK), falls es ihn gab und er aktualisiert worden ist. Wir könnten natürlich noch mehr machen, aber der aktuelle Anwendungscode erfüllt die Anforderungen und bietet direkte und saubere interne und externe APIs:

@PutMapping("/{id}")

ResponseEntity<Coffee> putCoffee(@PathVariable String id,

@RequestBody Coffee coffee) {

int coffeeIndex = -1;

for (Coffee c: coffees) {

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

coffeeIndex = coffees.indexOf(c);

coffees.set(coffeeIndex, coffee);

}

}

return (coffeeIndex == -1) ?

new ResponseEntity<>(postCoffee(coffee), HttpStatus.CREATED) :

new ResponseEntity<>(coffee, HttpStatus.OK);

}

Spring Boot

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