Een inleiding tot Spring HATEOAS

REST Top

Ik heb zojuist het nieuwe aangekondigd Leer de lente natuurlijk, gericht op de basisprincipes van Spring 5 en Spring Boot 2:

>> BEKIJK DE CURSUS

1. Overzicht

Dit artikel legt het proces uit van het maken van een hypermedia-gestuurde REST-webservice met behulp van het Spring HATEOAS-project.

2. Lente-HATEOAS

Het Spring HATEOAS-project is een bibliotheek met API's die we kunnen gebruiken om eenvoudig REST-representaties te maken die het principe van HATEOAS (Hypertext as the Engine of Application State) volgen.

Over het algemeen houdt het principe in dat de API de klant door de applicatie moet leiden door relevante informatie over de volgende mogelijke stappen te retourneren, samen met elk antwoord.

In dit artikel gaan we een voorbeeld bouwen met Spring HATEOAS met als doel de client en server te ontkoppelen en de API in theorie zijn URI-schema te laten wijzigen zonder clients te verbreken.

3. Voorbereiding

Laten we eerst de Spring HATEOAS-afhankelijkheid toevoegen:

 org.springframework.boot spring-boot-starter-hateoas 2.1.4.RELEASE 

Als we Spring Boot niet gebruiken, kunnen we de volgende bibliotheken aan ons project toevoegen:

 org.springframework.hateoas spring-hateoas 0.25.1.RELEASE org.springframework.plugin spring-plugin-core 1.2.0.RELEASE 

Zoals altijd kunnen we zoeken in de nieuwste versies van de starter HATEOAS, de spring-hateoas en de spring-plugin-core afhankelijkheden in Maven Central.

Vervolgens hebben we de Klant bron zonder Spring HATEOAS-ondersteuning:

openbare klasse Customer {private String customerId; private String klantnaam; private String companyName; // standaard getters en setters} 

En we hebben een controllerklasse zonder Spring HATEOAS-ondersteuning:

@RestController @RequestMapping (value = "/ customers") publieke klasse CustomerController {@Autowired private CustomerService customerService; @GetMapping ("/ {customerId}") openbare Customer getCustomerById (@PathVariable String customerId) {return customerService.getCustomerDetail (customerId); }} 

eindelijk, de Klant resource vertegenwoordiging:

{"customerId": "10A", "customerName": "Jane", "customerCompany": "ABC Company"} 

4. HATEOAS-ondersteuning toevoegen

In een Spring HATEOAS-project hoeven we de Servlet-context niet op te zoeken of de padvariabele samen te voegen met de basis-URI.

In plaats daarvan, Spring HATEOAS biedt drie abstracties voor het maken van de URI - RepresentationModel, Link en WebMvcLinkBuilder. We kunnen deze gebruiken om de metadata te creëren en deze te koppelen aan de resource-representatie.

4.1. Hypermedia-ondersteuning toevoegen aan een bron

Het project biedt een basisklasse met de naam Vertegenwoordiging Model om te erven van bij het maken van een bronweergave:

openbare klasse Klant verlengt RepresentationModel {private String customerId; private String klantnaam; private String companyName; // standaard getters en setters} 

De Klant resource strekt zich uit van de Vertegenwoordiging Model klasse om de toevoegen() methode. Dus als we eenmaal een link hebben gemaakt, kunnen we die waarde gemakkelijk instellen op de resource-weergave zonder er nieuwe velden aan toe te voegen.

4.2. Links maken

Spring HATEOAS biedt een Koppeling object om de metagegevens (locatie of URI van de bron) op te slaan.

Eerst maken we handmatig een eenvoudige link:

Link link = new Link ("// localhost: 8080 / spring-security-rest / api / customers / 10A"); 

De Koppeling object volgt het Atoom link syntaxis en bestaat uit een rel die de relatie tot de bron identificeert en href attribuut dat de daadwerkelijke link zelf is.

Hier is hoe de Klant resource ziet er nu naar uit dat het de nieuwe link bevat:

{"customerId": "10A", "customerName": "Jane", "customerCompany": "ABC Company", "_links": {"self": {"href": "// localhost: 8080 / spring-security -rest / api / klanten / 10A "}}} 

De URI die aan het antwoord is gekoppeld, wordt gekwalificeerd als een zelf koppeling. De semantiek van de zelf relatie is duidelijk - het is gewoon de canonieke locatie waar de bron toegankelijk is.

4.3. Betere links creëren

Een andere zeer belangrijke abstractie die de bibliotheek aanbiedt, is de WebMvcLinkBuilder - wat het bouwen van URI's vereenvoudigt door hardcoded de links te vermijden.

Het volgende fragment toont het bouwen van de klantzelflink met behulp van de WebMvcLinkBuilder klasse:

linkTo (CustomerController.class) .slash (customer.getCustomerId ()). withSelfRel (); 

Laten we eens kijken:

  • de link naar() methode inspecteert de controller-klasse en verkrijgt zijn root-mapping
  • de schuine streep() methode voegt de Klanten ID waarde als de padvariabele van de link
  • eindelijk, de withSelfMethod () kwalificeert de relatie als een zelfkoppeling

5. Relaties

In het vorige gedeelte hebben we een zelfverwijzende relatie laten zien. Bij complexere systemen kunnen echter ook andere relaties betrokken zijn.

Bijvoorbeeld een klant kan een relatie hebben met bestellingen. Laten we het Bestellen klasse ook als hulpmiddel:

openbare klasse Order breidt RepresentationModel {private String orderId uit; particuliere dubbele prijs; private int hoeveelheid; // standaard getters en setters} 

Op dit punt kunnen we het Klantcontroller met een methode die alle bestellingen van een bepaalde klant retourneert:

@GetMapping (value = "/ {customerId} / orders", produce = {"application / hal + json"}) openbare CollectionModel getOrdersForCustomer (@PathVariable laatste String customerId) {List orders = orderService.getAllOrdersForCustomer (customerId); voor (laatste orderorder: orders) {Link selfLink = linkTo (methodOn (CustomerController.class) .getOrderById (customerId, order.getOrderId ())). withSelfRel (); order.add (selfLink); } Link link = linkTo (methodOn (CustomerController.class) .getOrdersForCustomer (customerId)). WithSelfRel (); CollectionModel resultaat = nieuw CollectionModel (bestellingen, link); resultaat teruggeven; } 

Onze methode retourneert een CollectieModel bezwaar maken om te voldoen aan het HAL-retourtype, evenals een “_zelf" link voor elk van de bestellingen en de volledige lijst.

Belangrijk om hierbij op te merken is dat de hyperlink voor de klantbestellingen afhankelijk is van de mapping van getOrdersForCustomer () methode. We zullen naar dit soort koppelingen verwijzen als methodekoppelingen en laten zien hoe de WebMvcLinkBuilder kunnen helpen bij hun creatie.

6. Links naar controllermethoden

De WebMvcLinkBuilder biedt uitgebreide ondersteuning voor Spring MVC-controllers. Het volgende voorbeeld laat zien hoe u HATEOAS-hyperlinks bouwt op basis van het getOrdersForCustomer () methode van de Klantcontroller klasse:

Link ordersLink = linkTo (methodOn (CustomerController.class) .getOrdersForCustomer (customerId)). WithRel ("allOrders"); 

De methodOn () verkrijgt de methodemapping door een dummy-aanroep van de doelmethode uit te voeren op de proxycontroller en stelt de Klanten ID als padvariabele van de URI.

7. Spring HATEOAS in actie

Laten we de zelfkoppeling en het maken van methodekoppelingen allemaal samen in een getAllCustomers () methode:

@GetMapping (produceert = {"application / hal + json"}) openbare CollectionModel getAllCustomers () {List allCustomers = customerService.allCustomers (); voor (Klant klant: allCustomers) {String customerId = customer.getCustomerId (); Link selfLink = linkTo (CustomerController.class) .slash (customerId) .withSelfRel (); customer.add (selfLink); if (orderService.getAllOrdersForCustomer (customerId) .size ()> 0) {Link ordersLink = linkTo (methodOn (CustomerController.class) .getOrdersForCustomer (klantId)). withRel ("allOrders"); customer.add (ordersLink); }} Link link = linkTo (CustomerController.class) .withSelfRel (); CollectionModel resultaat = nieuw CollectionModel (allCustomers, link); resultaat teruggeven; }

Laten we vervolgens het getAllCustomers () methode:

curl // localhost: 8080 / spring-security-rest / api / customers 

En bekijk het resultaat:

{"_embedded": {"customerList": [{"customerId": "10A", "customerName": "Jane", "companyName": "ABC Company", "_links": {"self": {"href" : "// localhost: 8080 / spring-security-rest / api / customers / 10A"}, "allOrders": {"href": "// localhost: 8080 / spring-security-rest / api / customers / 10A / bestellingen "}}}, {" customerId ":" 20B "," customerName ":" Bob "," companyName ":" XYZ Company "," _links ": {" self ": {" href ":" // localhost : 8080 / spring-security-rest / api / customers / 20B "}," allOrders ": {" href ":" // localhost: 8080 / spring-security-rest / api / customers / 20B / orders "}}} , {"customerId": "30C", "customerName": "Tim", "companyName": "CKV Company", "_links": {"self": {"href": "// localhost: 8080 / spring- security-rest / api / customers / 30C "}}}]}," _links ": {" self ": {" href ":" // localhost: 8080 / spring-security-rest / api / customers "}}}

Binnen elke resource-representatie is er een zelf link en de alle bestellingen link om alle bestellingen van een klant te extraheren. Als een klant geen bestellingen heeft, wordt de link voor bestellingen niet weergegeven.

Dit voorbeeld laat zien hoe Spring HATEOAS API-vindbaarheid bevordert in een andere webservice. Als de link bestaat, kan de klant deze volgen en alle bestellingen voor een klant ontvangen:

curl // localhost: 8080 / spring-security-rest / api / customers / 10A / orders 
{"_embedded": {"orderList": [{"orderId": "001A", "price": 150, "kwantiteit": 25, "_links": {"self": {"href": "// localhost : 8080 / spring-security-rest / api / customers / 10A / 001A "}}}, {" orderId ":" 002A "," price ": 250," quantity ": 15," _links ": {" self " : {"href": "// localhost: 8080 / spring-security-rest / api / customers / 10A / 002A"}}}]}, "_links": {"self": {"href": "// localhost: 8080 / spring-security-rest / api / customers / 10A / orders "}}}

8. Conclusie

In deze zelfstudie hebben we besproken hoe u dit kunt doen bouw een hypermedia-gedreven Spring REST-webservice met behulp van het Spring HATEOAS-project.

In het voorbeeld zien we dat de klant een enkel toegangspunt tot de applicatie kan hebben en dat verdere acties kunnen worden ondernomen op basis van de metadata in de responsweergave.

Hierdoor kan de server zijn URI-schema wijzigen zonder de client te breken. Ook kan de applicatie nieuwe mogelijkheden adverteren door nieuwe links of URI's in de weergave te plaatsen.

Ten slotte is de volledige implementatie van dit artikel te vinden in het GitHub-project.

REST onder

Ik heb zojuist het nieuwe aangekondigd Leer de lente natuurlijk, gericht op de basisprincipes van Spring 5 en Spring Boot 2:

>> BEKIJK DE CURSUS