Komme i gang med GraphQL og Spring Boot

1. Introduksjon

GraphQL er et relativt nytt konsept fra Facebook som faktureres som et alternativ til REST for web-API-er.

Denne artikkelen vil gi en introduksjon til å sette opp en GraphQL-server ved hjelp av Spring Boot, slik at den kan legges til eksisterende applikasjoner eller brukes i nye.

2. Hva er? GraphQL?

Tradisjonelle REST API-er fungerer med konseptet ressurser som serveren administrerer. Disse ressursene kan manipuleres på noen standard måter, i henhold til de forskjellige HTTP-verbene. Dette fungerer veldig bra så lenge APIen vår passer til ressurskonseptet, men faller raskt fra hverandre når vi trenger å avvike fra det.

Dette lider også når klienten trenger data fra flere ressurser samtidig. For eksempel å be om et blogginnlegg og kommentarer. Dette løses vanligvis ved enten å få klienten til å gjøre flere forespørsler eller ved å få serveren til å levere ekstra data som ikke alltid er nødvendig, noe som fører til større svarstørrelser.

GraphQL tilbyr en løsning på begge disse problemene. Det gjør det mulig for klienten å spesifisere nøyaktig hvilke data som er ønsket, inkludert fra å navigere i underordnede ressurser i en enkelt forespørsel, og gir mulighet for flere spørsmål i en enkelt forespørsel.

Det fungerer også på en mye mer RPC-måte, ved å bruke navngitte spørsmål og mutasjoner i stedet for et standard obligatorisk sett med handlinger. Dette fungerer for å sette kontrollen der den hører hjemme, med API-utvikleren som spesifiserer hva som er mulig, og API-forbrukeren hva som er ønsket.

For eksempel kan en blogg tillate følgende spørsmål:

spørring {recentPosts (count: 10, offset: 0) {id title category author {id name thumbnail}}}

Dette spørsmålet vil:

  • be om de ti siste innleggene
  • for hvert innlegg, be om ID, tittel og kategori
  • for hvert innlegg be forfatteren, returnere ID, navn og miniatyrbilde

I et tradisjonelt REST API trenger dette enten 11 forespørsler - 1 for innleggene og 10 for forfatterne - eller må inkludere forfatterdetaljene i innleggsdetaljene.

2.1. GraphQL skjemaer

GraphQL-serveren avslører et skjema som beskriver API. Denne ordningen består av typedefinisjoner. Hver type har ett eller flere felt, som hver tar null eller flere argumenter og returnerer en bestemt type.

Grafen består av måten disse feltene er nestet med hverandre. Merk at det ikke er behov for at grafen er syklisk - sykluser er helt akseptable - men det er rettet. Det vil si at klienten kan komme fra ett felt til sine barn, men det kan ikke automatisk komme tilbake til foreldrene med mindre skjemaet definerer dette eksplisitt.

Et eksempel på GrafQL-skjema for en blogg kan inneholde følgende definisjoner, som beskriver et innlegg, en forfatter av innlegget og et rotspørsmål for å få de siste innleggene på bloggen.

skriv innlegg {id: ID! tittel: String! tekst: String! kategori: Stringforfatter: Forfatter! } skriv Forfatter {id: ID! navn: String! miniatyrbilde: Stringinnlegg: [Innlegg]! } # Root Query for applikasjonstypen Query {recentPosts (count: Int, offset: Int): [Post]! } # Root Mutation for applikasjonstypen Mutation {writePost (tittel: String !, tekst: String !, category: String): Post! }

"!" på slutten av noen navn indikerer at dette er en ikke-nullbar type. Enhver type som ikke har dette kan være null i svaret fra serveren. GraphQL-tjenesten håndterer disse riktig, slik at vi kan be om underordnede felt av ugyldige typer trygt.

GraphQL-tjenesten eksponerer også selve skjemaet ved hjelp av et standard sett med felt, slik at enhver klient kan spørre om skjemadefinisjonen på forhånd.

Dette kan gjøre det mulig for klienten å oppdage automatisk når skjemaet endres, og tillate klienter som dynamisk tilpasser seg måten skjemaet fungerer på. Et utrolig nyttig eksempel på dette er GraphiQL-verktøyet - diskutert senere - som lar oss samhandle med hvilken som helst GraphQL API.

3. Introduksjon av GraphQL Spring Boot Starter

Spring Boot GraphQL Starter tilbyr en fantastisk måte å få en GraphQL-server til å kjøre på veldig kort tid. Kombinert med GraphQL Java Tools-biblioteket trenger vi bare å skrive koden som er nødvendig for tjenesten vår.

3.1. Sette opp tjenesten

Alt vi trenger for at dette skal fungere er de riktige avhengighetene:

 com.graphql-java graphql-spring-boot-starter 5.0.2 com.graphql-java graphql-java-tools 5.2.4 

Spring Boot plukker automatisk opp disse og setter de rette håndtererne til å fungere automatisk.

Som standard vil dette utsette GraphQL-tjenesten på / graphql endepunkt for søknaden vår og vil godta POST-forespørsler som inneholder GraphQL-nyttelasten. Dette endepunktet kan tilpasses i vår application.properties filen om nødvendig.

3.2. Skrive skjemaet

GraphQL Tools-biblioteket fungerer ved å behandle GraphQL Schema-filer for å bygge riktig struktur og deretter koble spesielle bønner til denne strukturen. Spring Boot GraphQL starter starter automatisk disse skjemafilene.

Disse filene må lagres med filtypen “.graphqls”Og kan være til stede hvor som helst på klassestien. Vi kan også ha så mange av disse filene som ønsket, slik at vi kan dele ordningen opp i moduler som ønsket.

Det ene kravet er at det må være nøyaktig ett rotspørsmål, og opptil en rotmutasjon. Dette kan ikke deles på tvers av filer, i motsetning til resten av ordningen. Dette er en begrensning av selve definisjonen av GraphQL Schema, og ikke av Java-implementeringen.

3.3. Root Query Resolver

Rotspørsmålet må ha spesielle bønner definert i vårkonteksten for å håndtere de forskjellige feltene i dette rotspørsmålet. I motsetning til skjemadefinisjonen er det ingen begrensning at det bare er en enkelt vårbønne for rotspørsmålsfeltene.

De eneste kravene er at bønnene implementeres GraphQLQueryResolver og at hvert felt i rotspørringen fra skjemaet har en metode i en av disse klassene med samme navn.

offentlig klasse Query implementerer GraphQLQueryResolver {private PostDao postDao; public List getRecentPosts (int count, int offset) {return postsDao.getRecentPosts (count, offset); }}

Navnene på metoden må være ett av følgende, i denne rekkefølgen:

  1. er - bare hvis feltet er av typen Boolsk

Metoden må ha parametere som tilsvarer eventuelle parametere i GraphQL-skjemaet, og kan eventuelt ta en endelig parameter av typen DataFetchingEnvironment.

Metoden må også returnere riktig returtype for typen i GraphQL-ordningen, slik vi er i ferd med å se. Noen enkle typer - String, Int, List, osv. - kan brukes med tilsvarende Java-typer, og systemet kartlegger dem bare automatisk.

Ovennevnte definerte metoden getRecentPosts som vil bli brukt til å håndtere alle GraphQL-spørsmål for Siste innlegg felt i skjemaet som ble definert tidligere.

3.4. Bruke bønner til å representere typer

Hver kompleks type i GraphQL-serveren er representert av en Java-bønne - enten lastet fra rotspørringen eller hvor som helst annet i strukturen. Den samme Java-klassen må alltid representere den samme GraphQL-typen, men navnet på klassen er ikke nødvendig.

Felter inne i Java-bønnen vil direkte tilordnes felt i GraphQL-responsen basert på navnet på feltet.

public class Post {private String id; privat strengetittel; privat streng kategori; private strengforfatterId; }

Eventuelle felt eller metoder på Java-bønnen som ikke tilordnes til GraphQL-skjemaet, blir ignorert, men vil ikke forårsake problemer. Dette er viktig for at feltoppløsere skal fungere.

For eksempel feltet authorId her tilsvarer ikke noe i skjemaet vi definerte tidligere, men det vil være tilgjengelig for neste trinn.

3.5. Feltresolvere for komplekse verdier

Noen ganger er verdien av et felt ikke trivielt å laste inn. Dette kan innebære databaseoppslag, komplekse beregninger eller noe annet. GraphQL Tools har et konsept med en feltoppløsning som brukes til dette formålet. Dette er vårbønner som kan gi verdier i stedet for databønnen.

Feltoppløseren er en hvilken som helst bønne i vårkonteksten som har samme navn som databønnen, med suffikset Resolver, og som implementerer GrafQLResolver grensesnitt. Metoder på feltoppløsningsbønne følger alle de samme reglene som på databønnen, men blir også gitt selve databønnen som en første parameter.

Hvis en feltoppløsningsenhet og databønnen begge har metoder for det samme GraphQL-feltet, vil feltoppløseren ha forrang.

offentlig klasse PostResolver implementerer GraphQLResolver {private AuthorDao authorDao; public Author getAuthor (Post post) {return authorDao.getAuthorById (post.getAuthorId ()); }}

Det faktum at disse feltoppløserne er lastet fra vårkonteksten er viktig. Dette gjør at de kan jobbe med andre vårstyrte bønner - for eksempel DAO.

Viktigere, Hvis klienten ikke ber om et felt, vil GraphQL Server aldri gjøre arbeidet for å hente det. Dette betyr at hvis en klient henter et innlegg og ikke ber om forfatteren, så getAuthor () metoden ovenfor vil aldri bli utført, og DAO-anropet vil aldri bli utført.

3.6. Nullable Values

GraphQL-skjemaet har konseptet at noen typer er ugyldige og andre ikke.

Dette kan håndteres i Java-koden ved å bruke nullverdier direkte, men likt den nye Valgfri type fra Java 8 kan brukes direkte her for ugyldige typer, og systemet vil gjøre det riktige med verdiene.

Dette er veldig nyttig da det betyr at Java-koden vår er tydeligere den samme som GraphQL-skjemaet fra metodedefinisjonene.

3.7. Mutasjoner

Så langt har alt vi har gjort handlet om å hente data fra serveren. GraphQL har også muligheten til å oppdatere dataene som er lagret på serveren, ved hjelp av mutasjoner.

Fra koden er det ingen grunn til at en spørring ikke kan endre data på serveren. Vi kan enkelt skrive spørringsløsere som godtar argumenter, lagrer nye data og returnerer endringene. Å gjøre dette vil føre til overraskende bivirkninger for API-klientene, og regnes som dårlig praksis.

I stedet, Mutasjoner bør brukes til å informere klienten om at dette vil føre til en endring av dataene som lagres.

Mutasjoner er definert i Java-koden ved hjelp av klasser som implementeres GraphQLMutationResolver i stedet for GraphQLQueryResolver.

Ellers gjelder alle de samme reglene som for spørsmål. Returverdien fra et mutasjonsfelt behandles deretter nøyaktig den samme som fra et spørringsfelt, slik at også nestede verdier kan hentes.

offentlig klasse Mutasjon implementerer GraphQLMutationResolver {private PostDao postDao; public Post writePost (Stringtittel, Stringtekst, Stringkategori) {retur postDao.savePost (tittel, tekst, kategori); }}

4. Introduksjon av GraphiQL

GraphQL har også et ledsagerverktøy kalt GraphiQL. Dette er et brukergrensesnitt som er i stand til å kommunisere med hvilken som helst GraphQL Server og utføre spørsmål og mutasjoner mot den. En nedlastbar versjon av den finnes som en Electron-app og kan hentes herfra.

Det er også mulig å inkludere den nettbaserte versjonen av GraphiQL i applikasjonen vår automatisk, ved å legge til avhengigheten av GraphiQL Spring Boot Starter:

 com.graphql-java graphiql-spring-boot-starter 5.0.2 

Dette fungerer bare hvis vi er vert for GraphQL API på standard endepunkt for / graphql skjønt, så den frittstående applikasjonen vil være nødvendig hvis det ikke er tilfelle.

5. Sammendrag

GraphQL er en veldig spennende ny teknologi som potensielt kan revolusjonere måten web-API-er er utviklet på.

Kombinasjonen av Spring Boot GraphQL Starter og GraphQL Java Tools-bibliotekene gjør det utrolig enkelt å legge til denne teknologien i alle nye eller eksisterende Spring Boot-applikasjoner.

Kodebiter finner du på GitHub.


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