En introduktion til foråret HATEOAS

REST Top

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

1. Oversigt

Denne artikel forklarer processen med oprettelse af hypermediadrevet REST-webservice ved hjælp af Spring HATEOAS-projektet.

2. Spring-HATEOAS

Spring HATEOAS-projektet er et bibliotek med API'er, som vi kan bruge til let at oprette REST-repræsentationer, der følger HATEOAS-princippet (Hypertext as the Engine of Application State).

Generelt betyder princippet, at API'en skal guide klienten gennem applikationen ved at returnere relevant information om de næste potentielle trin sammen med hvert svar.

I denne artikel vil vi bygge et eksempel ved hjælp af Spring HATEOAS med det formål at afkoble klienten og serveren og teoretisk tillade API'et at ændre sit URI-skema uden at bryde klienter.

3. Forberedelse

Lad os først tilføje Spring HATEOAS afhængighed:

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

Hvis vi ikke bruger Spring Boot, kan vi tilføje følgende biblioteker til vores projekt:

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

Som altid kan vi søge i de nyeste versioner af starteren HATEOAS, spring-hateoas og spring-plugin-core afhængigheder i Maven Central.

Dernæst har vi Kunde ressource uden Spring HATEOAS support:

offentlig klasse kunde {privat streng kunde-id; privat streng kundenavn; private String companyName; // standard getters og setter} 

Og vi har en controller klasse uden Spring HATEOAS support:

@RestController @RequestMapping (værdi = "/ kunder") offentlig klasse CustomerController {@Autowired privat CustomerService kundeservice; @GetMapping ("/ {customerId}") offentlig kunde getCustomerById (@PathVariable String customerId) {return customerService.getCustomerDetail (customerId); }} 

Endelig blev Kunde ressourcerepræsentation:

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

4. Tilføjelse af HATEOAS-support

I et Spring HATEOAS-projekt behøver vi ikke hverken slå op i Servlet-sammenhængen eller sammenkæde stivariablen til basis-URI.

I stedet, Spring HATEOAS tilbyder tre abstraktioner til oprettelse af URI - RepresentationModel, Link og WebMvcLinkBuilder. Vi kan bruge disse til at oprette metadataene og knytte dem til ressourcerepræsentationen.

4.1. Tilføjelse af Hypermedia Support til en ressource

Projektet giver en basisklasse kaldet RepræsentationModel at arve fra, når du opretter en ressourcerepræsentation:

offentlig klasse kunde udvider RepresentationModel {private String customerId; privat streng kundenavn; private String companyName; // standard getters og setter} 

Det Kunde ressource strækker sig fra RepræsentationModel klasse til at arve tilføje() metode. Så når vi opretter et link, kan vi nemt indstille denne værdi til ressourcerepræsentationen uden at tilføje nye felter til den.

4.2. Oprettelse af links

Spring HATEOAS giver en Link modsætter sig at gemme metadataene (ressourceens placering eller URI).

Først opretter vi et simpelt link manuelt:

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

Det Link objekt følger Atom link syntaks og består af en rel som identificerer relation til ressourcen og href attribut, som er selve linket.

Sådan gør du Kunde ressource ser nu ud, da den indeholder det nye link:

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

URI'en, der er knyttet til svaret, er kvalificeret som en selv link. Semantikken i selv forholdet er klart - det er simpelthen den kanoniske placering, ressourcen kan tilgås på.

4.3. Oprettelse af bedre links

En anden meget vigtig abstraktion, som biblioteket tilbyder, er det WebMvcLinkBuilder - hvilket forenkler opbygningen af ​​URI'er ved at undgå hardkodede links.

Følgende uddrag viser opbygning af kundens selvlink ved hjælp af WebMvcLinkBuilder klasse:

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

Lad os kigge på det:

  • det link til() metoden inspicerer controller-klassen og opnår sin rodmapping
  • det skråstreg() metoden tilføjer Kunde ID værdi som sti-variablen for linket
  • endelig, den withSelfMethod () kvalificerer forholdet som en selvforbindelse

5. Forhold

I det foregående afsnit har vi vist en selvhenvisende relation. Imidlertid kan mere komplekse systemer også involvere andre relationer.

F.eks kunde kan have et forhold til ordrer. Lad os modellere Bestille klasse som en ressource:

public class Order udvider RepresentationModel {private String orderId; privat dobbelt pris; privat int mængde; // standard getters og setter} 

På dette tidspunkt kan vi udvide CustomerController med en metode, der returnerer alle ordrer fra en bestemt kunde:

@GetMapping (værdi = "/ {customerId} / ordrer", producerer = {"applikation / hal + json"}) offentlig CollectionModel getOrdersForCustomer (@PathVariable final String customerId) {List orders = orderService.getAllOrdersForCustomer (customerId); for (endelig ordreordre: ordrer) {Link selfLink = linkTo (methodOn (CustomerController.class) .getOrderById (customerId, order.getOrderId ())). withSelfRel (); order.add (selfLink); } Link link = linkTo (methodOn (CustomerController.class) .getOrdersForCustomer (customerId)). WithSelfRel (); CollectionModel resultat = nyt CollectionModel (ordrer, link); returresultat } 

Vores metode returnerer a CollectionModel modsætter sig at overholde HAL-returtypen samt en “_selv" link til hver af ordrene og den fulde liste.

En vigtig ting at bemærke her er, at hyperlinket til kundeordrer afhænger af kortlægningen af getOrdersForCustomer () metode. Vi refererer til disse typer links som metodelinks og viser, hvordan WebMvcLinkBuilder kan hjælpe med deres oprettelse.

6. Links til controller-metoder

Det WebMvcLinkBuilder tilbyder rig support til Spring MVC Controllers. Følgende eksempel viser, hvordan man bygger HATEOAS-hyperlinks baseret på getOrdersForCustomer () metode til CustomerController klasse:

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

Det methodOn () opnår metoden kortlægning ved at foretage dummy påkaldelse af målmetoden på proxy-controlleren og indstiller Kunde ID som sti-variablen for URI.

7. Spring HATEOAS i aktion

Lad os sætte skabelsen af ​​selvlink og metodelink sammen i en getAllCustomers () metode:

@GetMapping (producerer = {"applikation / hal + json"}) offentlig CollectionModel getAllCustomers () {Liste allCustomers = customerService.allCustomers (); for (Kundekunde: 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 (customerId)). withRel ("allOrders"); customer.add (ordersLink); }} Linklink = linkTo (CustomerController.class) .withSelfRel (); CollectionModel resultat = nyt CollectionModel (allCustomers, link); returresultat }

Lad os derefter kalde på getAllCustomers () metode:

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

Og undersøge resultatet:

{"_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 / ordrer "}}}, {" 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- sikkerhed-hvile / api / kunder / 30C "}}}]}," _links ": {" self ": {" href ":" // localhost: 8080 / spring-security-rest / api / customers "}}}

Inden for hver ressourcerepræsentation er der en selv link og alle ordrer link for at udtrække alle ordrer fra en kunde. Hvis en kunde ikke har ordrer, vises linket til ordrer ikke.

Dette eksempel viser, hvordan Spring HATEOAS fremmer API-opdagelsesevne i en restwebtjeneste. Hvis linket findes, kan klienten følge det og få alle ordrer til en kunde:

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

8. Konklusion

I denne vejledning har vi diskuteret, hvordan man gør det opbygge en hypermediedrevet Spring REST-webservice ved hjælp af Spring HATEOAS-projektet.

I eksemplet ser vi, at klienten kan have et enkelt indgangspunkt til applikationen, og der kan udføres yderligere handlinger baseret på metadataene i svarrepræsentationen.

Dette giver serveren mulighed for at ændre sit URI-skema uden at bryde klienten. Applikationen kan også reklamere for nye muligheder ved at placere nye links eller URI'er i repræsentationen.

Endelig kan den fulde implementering af denne artikel findes i GitHub-projektet.

REST bunden

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN