Fjern afskedigelser i RAML med ressourcetyper og træk

Denne artikel er en del af en serie: • Introduktion til RAML - RESTful API Modeling Language

• Eliminer afskedigelser i RAML med ressourcetyper og træk (nuværende artikel) • Modulær RAML ved hjælp af Inkluderer, biblioteker, overlejringer og udvidelser

• Definer brugerdefinerede RAML-egenskaber ved hjælp af kommentarer

1. Oversigt

I vores RAML tutorial artikel introducerede vi RESTful API-modelleringssprog og oprettede en simpel API-definition baseret på en enkelt enhed kaldet Foo. Forestil dig nu en reel API, hvor du har flere ressourcer af enhedstype, som alle har de samme eller lignende GET-, POST-, PUT- og DELETE-operationer. Du kan se, hvordan din API-dokumentation hurtigt kan blive kedelig og gentagne.

I denne artikel viser vi, hvordan brugen af ressourcetyper og træk funktioner i RAML kan eliminere afskedigelser i ressource- og metodedefinitioner ved at udpakke og parametrere almindelige sektioner og derved fjerne kopier og indsæt fejl, mens du gør dine API-definitioner mere koncise.

2. Vores API

For at demonstrere fordelene ved ressourcetyper og trækudvider vi vores oprindelige API ved at tilføje ressourcer til en anden enhedstype kaldet Bar. Her er de ressourcer, der udgør vores reviderede API:

  • GET / api / v1 / foos
  • POST / api / v1 / foos
  • GET / api / v1 / foos / {fooId}
  • PUT / api / v1 / foos / {fooId}
  • SLET / api / v1 / foos / {fooId}
  • GET / api / v1 / foos / name / {name}
  • GET / api / v1 / foos? Name = {name} & ownerName = {ownerName}
  • GET / api / v1 / søjler
  • POST / api / v1 / søjler
  • GET / api / v1 / barer / {barId}
  • PUT / api / v1 / søjler / {barId}
  • SLET / api / v1 / søjler / {barId}
  • GET / api / v1 / søjler / fooId / {fooId}

3. Genkendelse af mønstre

Når vi læser gennem listen over ressourcer i vores API, begynder vi at se nogle mønstre opstå. For eksempel er der et mønster for URI'er og metoder, der bruges til at oprette, læse, opdatere og slette enkelte enheder, og der er et mønster for URI'er og metoder, der bruges til at hente samlinger af enheder. Samlings- og samlingsgenstandsmønsteret er et af de mere almindelige mønstre, der bruges til at udtrække ressourcetyper i RAML-definitioner.

Lad os se på et par sektioner af vores API:

[Bemærk: I nedenstående kodestykker angiver en linje, der kun indeholder tre prikker (...), at nogle linjer springes over for kortfattethed.]

/ foos: get: beskrivelse: | Angiv alle foos, der matcher forespørgselskriterier, hvis de findes; Ellers anfør alle foos forespørgselParametre: navn ?: streng ejer Navn ?: streng svar: 200: body: application / json: type: Foo [] post: beskrivelse: Opret en ny foo body: application / json: type: Foo svar: 201: body: application / json: type: Foo ... / barer: get: beskrivelse: | Liste over alle søjler, der matcher forespørgselskriterier, hvis de findes; Ellers lister alle bjælker queryParameters: navn ?: streng ejernavn ?: streng svar: 200: body: application / json: type: Bar [] post: beskrivelse: Opret en ny bar body: application / json: type: Bar svar: 201: body: application / json: type: Bar

Når vi sammenligner RAML-definitionerne af / foos og / søjler ressourcer, inklusive de anvendte HTTP-metoder, kan vi se flere afskedigelser blandt de forskellige egenskaber for hver, og vi ser igen, at mønstre begynder at dukke op.

Uanset hvor der er et mønster i enten en ressource- eller metodedefinition, er der en mulighed for at bruge en RAML ressourcetype eller egenskab.

4. Ressourcetyper

For at implementere de mønstre, der findes i API'en, ressourcetyper brug reserverede og brugerdefinerede parametre omgivet af dobbelte vinkelparenteser (<>).

4.1 Reserverede parametre

To reserverede parametre kan bruges i definitioner af ressourcetype:

  • <> repræsenterer hele URI (efter baseURI), og
  • <> repræsenterer den del af URI, der følger skråstreg til højre (/) og ignorerer eventuelle seler {}.

Når de behandles i en ressourcedefinition, beregnes deres værdier baseret på den ressource, der defineres.

I betragtning af ressourcen / foos, for eksempel, <> ville evaluere til “/ foos” og <>ville evaluere til “foos”.

I betragtning af ressourcen / foos / {fooId}, <> ville evaluere til “/ foos / {fooId}” og <>ville evaluere til “foos”.

4.2 Brugerdefinerede parametre

EN ressourcetype definition kan også indeholde brugerdefinerede parametre. I modsætning til de reserverede parametre, hvis værdier bestemmes dynamisk baseret på den ressource, der defineres, skal brugerdefinerede parametre tildeles værdier, uanset hvor ressourcetype indeholder dem bruges, og disse værdier ændres ikke.

Brugerdefinerede parametre kan erklæres i begyndelsen af ​​en ressourcetype definition, selvom det ikke er nødvendigt og ikke er almindelig praksis, da læseren normalt kan finde ud af deres tilsigtede brug givet deres navne og den sammenhæng, hvori de bruges.

4.3 Parameterfunktioner

En håndfuld nyttige tekstfunktioner er tilgængelige til brug overalt, hvor en parameter bruges til at omdanne den udvidede værdi af parameteren, når den behandles i en ressourcedefinition.

Her er de tilgængelige funktioner til transformation af parametre:

  • !singulariser
  • !pluralisere
  • !store bogstaver
  • !små bogstaver
  • !store bogstaver
  • !nedre kuffert
  • !upperunderscorecase
  • !lavereundersøgelse
  • !upperhyphencase
  • !laverehyphencase

Funktioner anvendes til en parameter ved hjælp af følgende konstruktion:

<<parameternavn | !funktionsnavn>>

Hvis du har brug for mere end en funktion for at opnå den ønskede transformation, adskiller du hvert funktionsnavn med rørsymbolet (“|”) og lægger et udråbstegn (!) Foran hver anvendte funktion.

For eksempel givet ressourcen / foos, hvor <<resourcePathName>> vurderer til "foos":

  • <<resourcePathName | !singulariser>> ==> “foo”
  • <<resourcePathName | !store bogstaver>> ==> “FOOS”
  • <<resourcePathName | !singulariser | !store bogstaver>> ==> “FOO”

Og givet ressourcen / barer / {barId}, hvor <<resourcePathName>> vurderes til "søjler":

  • <<resourcePathName | !store bogstaver>> ==> “BARS”
  • <<resourcePathName | !store bogstaver>> ==> “Bar”

5. Udpakning af en ressourcetype til samlinger

Lad os omformulere / foos og / søjler ressource definitioner vist ovenfor ved hjælp af en ressourcetype for at fange de fælles egenskaber. Vi bruger den reserverede parameter <>og den brugerdefinerede parameter <> til at repræsentere den anvendte datatype.

5.1 Definition

Her er en ressourcetype definition, der repræsenterer en samling varer:

resourceTypes: collection: usage: Brug denne resourceType til at repræsentere enhver samling af varebeskrivelse: En samling af <> get: beskrivelse: Få alle <>, valgfrit filtrerede svar: 200: body: application / json: type: <> [] post : beskrivelse: Opret et nyt <> svar: 201: body: application / json: type: <>

Bemærk, at i vores API, fordi vores datatyper kun er store, store versioner af vores basisressourcers navne, kunne vi have anvendt funktioner til <<resourcePathName>> parameter i stedet for at introducere den brugerdefinerede <<typenavn>> parameter for at opnå det samme resultat for denne del af API:

resourceTypes: collection: ... get: ... type: <> [] post: ... type: <>

5.2 Anvendelse

Brug af ovenstående definition, der inkorporerer <<type Navn>> parameter, her er hvordan du vil anvende "samlingen" ressourcetype til ressourcerne / foos og /barer:

/ foos: type: {collection: {"typeName": "Foo"}} get: queryParameters: name ?: string ownerName ?: string ... / bars: type: {collection: {"typeName": "Bar"} }

Bemærk, at vi stadig er i stand til at inkorporere forskellene mellem de to ressourcer - i dette tilfælde, queryParameters sektion - mens du stadig drager fordel af alt det, som ressourcetype definition har at tilbyde.

6. Udpakning af en ressourcetype til enkeltgenstande i en samling

Lad os nu fokusere på den del af vores API, der beskæftiger sig med enkelte genstande i en samling: the / foos / {fooId} og / barer / {barId} ressourcer. Her er koden til/ foos / {fooId}:

/ foos: ... / {fooId}: get: beskrivelse: Få et Foo-svar: 200: body: application / json: type: Foo 404: body: application / json: type: Error example:! inkluderer eksempler / Error. json put: beskrivelse: Opdater en Foo-krop: applikation / json: type: Foo-svar: 200: krop: applikation / json: type: Foo 404: krop: applikation / json: type: Fejleksempel:! inkluderer eksempler / Error.json slet: beskrivelse: Slet et Foo-svar: 204: 404: body: application / json: type: Fejleksempel:! inkluderer eksempler / Error.json

Det / barer / {barId} ressource definition har også GET, PUT og DELETE metoder og er identisk med /foos / {fooId} definition, bortset fra forekomsterne af strengene "foo" og "bar" (og deres respektive pluraliserede og / eller store bogstaver).

6.1 Definition

Uddrag det mønster, vi lige har identificeret, her er hvordan vi definerer en ressourcetype for enkeltgenstande i en samling:

resourceTypes: ... element: brug: Brug denne resourceType til at repræsentere en enkelt varebeskrivelse: En enkelt <> get: beskrivelse: Få et <> svar: 200: body: application / json: type: <> 404: body: application / json: type: Fejleksempel:! inkluderer eksempler / Error.json put: beskrivelse: Opdater en <> body: applikation / json: type: <> svar: 200: body: application / json: type: <> 404: body : application / json: type: Fejleksempel:! inkluderer eksempler / Error.json delete: beskrivelse: Slet et <> svar: 204: 404: body: application / json: type: Fejleksempel:! include eksempler / Error.json

6.2 Anvendelse

Og her er, hvordan vi anvender "varen" ressourcetype:

/ foos: ... / {fooId}: type: {item: {"typeName": "Foo"}}
... / barer: ... / {barId}: type: {item: {"typeName": "Bar"}}

7. Træk

Hvorimod a ressourcetype bruges til at udtrække mønstre fra ressource definitioner, a egenskab bruges til at udtrække mønstre fra metodedefinitioner, der er almindelige på tværs af ressourcer.

7.1 Parametre

Sammen med <<resourcePath>> og <<resourcePathName>>, en yderligere reserveret parameter er tilgængelig til brug i egenskabsdefinitioner: <<methodName>> evaluerer til HTTP-metoden (GET, POST, PUT, SLET osv.) for hvilken egenskab er defineret. Brugerdefinerede parametre kan også forekomme inden for en egenskabsdefinition, og når de anvendes, påtager de sig værdien af ​​den ressource, hvori de anvendes.

7.2 Definition

Bemærk, at "varen" ressourcetype er stadig fuld af afskedigelser. Lad os se hvordan træk kan hjælpe med at fjerne dem. Vi starter med at udtrække en egenskab for enhver metode, der indeholder et anmodningsorgan:

træk: hasRequestItem: body: application / json: type: <>

Lad os nu udtrække træk for metoder, hvis normale reaktioner indeholder kroppe:

 hasResponseItem: svar: 200: body: application / json: type: <> hasResponseCollection: svar: 200: body: application / json: type: <> []

Endelig her er en egenskab for enhver metode, der kan returnere et 404-fejlrespons:

 hasNotFound: svar: 404: body: application / json: type: Fejleksempel:! inkluderer eksempler / Error.json

7.3 Anvendelse

Vi anvender dette egenskab til vores ressourcetyper:

resourceTypes: collection: usage: Brug denne resourceType til at repræsentere enhver samling af varebeskrivelse: En samling af <> get: description: | Få alle <>, valgfrit filtreret er: [hasResponseCollection: {typeName: <>}] post: beskrivelse: Opret et nyt <> is: [hasRequestItem: {typeName: <>}] element: brug: Brug denne resourceType til at repræsentere enhver enkelt varebeskrivelse: En enkelt <> get: beskrivelse: Få en <> er: [hasResponseItem: {typeName: <>}, hasNotFound] put: beskrivelse: Opdater en <> is: | [hasRequestItem: {typeName: <>}, hasResponseItem: {typeName: <>}, hasNotFound] delete: beskrivelse: Slet et <> er: [hasNotFound] svar: 204:

Vi kan også ansøge træk til metoder defineret inden for ressourcer. Dette er især nyttigt for "engangs" -scenarier, hvor en ressource-metode-kombination matcher en eller flere træk men matcher ikke nogen definerede ressourcetype:

/ foos: ... / name / {name}: get: beskrivelse: Liste over alle foos med et bestemt navn er: [hasResponseCollection: {typeName: Foo}]

8. Konklusion

I denne vejledning har vi vist, hvordan man i væsentlig grad kan reducere eller i nogle tilfælde eliminere afskedigelser fra en RAML API-definition.

Først identificerede vi de overflødige sektioner af vores ressourcer, genkendte deres mønstre og udtrukne ressourcetyper. Derefter gjorde vi det samme for de metoder, der var almindelige på tværs af ressourcer for at udtrække træk. Derefter var vi i stand til at fjerne yderligere afskedigelser ved at ansøge træk til vores ressourcetyper og til "engangs" ressource-metode kombinationer, der ikke strengt matchede en af ​​vores definerede ressourcetyper.

Som et resultat blev vores enkle API med ressourcer til kun to enheder reduceret fra 177 til lidt over 100 kodelinjer. For at lære mere om RAML ressourcetyper og træk, besøg RAML.org 1.0-specifikationen.

Det fuld implementering i denne vejledning kan findes i github-projektet.

Her er vores sidste RAML API i sin helhed:

#% RAML 1.0 titel: Baeldung Foo REST Services API-version: v1-protokoller: [HTTPS] baseUri: //rest-api.baeldung.com/api/{version} mediaType: application / json secureBy: basicAuth securitySchemes: basicAuth: beskrivelse: | Hver anmodning skal indeholde de nødvendige overskrifter til grundlæggende godkendelsestype: Grundlæggende godkendelse beskrevet af: overskrifter: Autorisation: beskrivelse: | Bruges til at sende den base64-kodede "brugernavn: adgangskode" legitimationsoplysninger type: strengrespons: 401: beskrivelse: | Uberettiget. Enten er det angivne kombination af brugernavn og adgangskode ugyldigt, eller brugeren har ikke adgang til det indhold, der leveres af den anmodede URL. types: Foo:! include types / Foo.raml Bar:! include types / Bar.raml Error:! include types / Error.raml resourceTypes: collection: use: Brug denne resourceType til at repræsentere en samling af varebeskrivelse: En samling af < > get: beskrivelse: | Hent alt <>, valgfrit filtreret er: [hasResponseCollection: {typeName: <>}] post: beskrivelse: | Opret et nyt <> is: [hasRequestItem: {typeName: <>}] element: brug: Brug denne resourceType til at repræsentere en enkelt varebeskrivelse: En enkelt <> get: beskrivelse: Få en <> er: [hasResponseItem: {typeName : <>}, hasNotFound] put: beskrivelse: Opdater en <> er: [hasRequestItem: {typeName: <>}, hasResponseItem: {typeName: <>}, hasNotFound] delete: beskrivelse: Slet en <> er: [hasNotFound ] svar: 204: træk: hasRequestItem: body: application / json: type: <> hasResponseItem: respons: 200: body: application / json: type: <> hasResponseCollection: svar: 200: body: application / json: type: < > [] hasNotFound: svar: 404: body: application / json: type: Fejleksempel:! inkluderer eksempler / Error.json / foos: type: {collection: {typeName: Foo}} get: queryParameters: name ?: string ownerName ?: string / {fooId}: type: {item: {typeName: Foo}} / name / {name}: get: description: Liste over alle foos med et bestemt navn er: [hasResponseCollection: {typeName: Foo}] / søjler : type: {collecti på: {typeName: Bar}} / {barId}: type: {item: {typeName: Bar}} / fooId / {fooId}: get: beskrivelse: Få alle bjælker til den matchende fooId er: [hasResponseCollection: {typeName: Bar}]
Næste » Modulær RAML ved hjælp af inkluderer, biblioteker, overlejringer og udvidelser « Tidligere introduktion til RAML - RESTful API-modelleringssprog

$config[zx-auto] not found$config[zx-overlay] not found