Uvod u GraphQL
1. Pregled
GraphQL je jezik upita, koji je Facebook stvorio u svrhu izrade klijentskih aplikacija zasnovanih na intuitivnoj i fleksibilnoj sintaksi, za opis njihovih zahtjeva za podacima i interakcija.
Jedan od primarnih izazova s tradicionalnim REST pozivima je nemogućnost klijenta da zatraži prilagođeni (ograničeni ili prošireni) skup podataka. U većini slučajeva, nakon što klijent zatraži podatke od poslužitelja, ili dobiva sva ili nijedno polje.
Druga je poteškoća rad i održavanje više krajnjih točaka. Kako platforma raste, time će se i broj povećavati. Stoga klijenti često trebaju tražiti podatke s različitih krajnjih točaka.
Prilikom izrade GraphQL poslužitelja, potreban je samo jedan URL za sve dohvaćanje i mutiranje podataka. Dakle, klijent može zatražiti skup podataka slanjem niza upita, opisujući ono što želi, poslužitelju.
2. Osnovna nomenklatura GraphQL
Pogledajmo osnovnu terminologiju GraphQL-a.
- Upit: je operacija samo za čitanje zatražena za GraphQL poslužitelj
- Mutacija: je operacija čitanja i pisanja koja se traži na GraphQL poslužitelju
- Razrješivač: U GraphQL-u, Razrješivač odgovoran je za mapiranje operacije i koda koji se izvodi na pozadini koji je odgovoran za obradu zahtjeva. Analogno je MVC pozadini u aplikaciji RESTFul
- Tip: A Tip definira oblik podataka odgovora koji se mogu vratiti s GraphQL poslužitelja, uključujući polja koja su rubovi drugih Vrste
- Ulazni: kao Tip, ali definira oblik ulaznih podataka koji se šalju na GraphQL poslužitelj
- Skalar: je primitivac Tip, kao što je a Niz, Int, Booleova, Plutatiitd
- Sučelje: Sučelje će pohraniti imena polja i njihove argumente, tako da GraphQL objekti mogu nasljeđivati od njega, osiguravajući upotrebu određenih polja
- Shema: U GraphQL-u Shema upravlja upitima i mutacijama, definirajući što se smije izvršiti na GraphQL poslužitelju
2.1. Učitavanje sheme
Postoje dva načina učitavanja sheme na GraphQL poslužitelj:
- korištenjem GraphQL-ovog jezika za definiranje sučelja (IDL)
- korištenjem jednog od podržanih programskih jezika
Pokažimo primjer pomoću IDL-a:
upišite Korisnik {firstName: String}
Sada, primjer definicije sheme pomoću Java koda:
GraphQLObjectType userType = newObject () .name ("User") .field (newFieldDefinition () .name ("firstName") .type (GraphQLString)) .build ();
3. Jezik definicije sučelja
Definicijski jezik sučelja (IDL) ili Jezik definicije sheme (SDL) najsažetiji je način određivanja GraphQL sheme. Sintaksa je dobro definirana i bit će usvojena u službenoj GraphQL specifikaciji.
Na primjer, stvorimo GraphQL shemu za korisnika / e-adrese koje se mogu odrediti ovako:
schema {query: QueryType} enum Spol {MALE FEMALE} upišite User {id: String! firstName: Niz! lastName: Niz! createdAt: DateTime! dob: Int! @default (value: 0) gender: [Gender]! e-mailovi: [Email!]! @relation (name: "E-mail")} upišite Email {id: String! e-mail: String! zadano: Int! @default (value: 0) user: User @relation (name: "E-mail")}
4. GraphQL-java
GraphQL-java je implementacija koja se temelji na specifikaciji i implementaciji JavaScript reference. Imajte na umu da za rad pravilno treba barem Java 8.
4.1. Bilješke GraphQL-jave
GraphQL također omogućuje upotrebu Java napomena za generiranje definicije sheme bez cjelokupnog koda stvorenog korištenjem tradicionalnog IDL pristupa.
4.2. Ovisnosti
Da bismo kreirali naš primjer, krenimo prvo s uvozom potrebne ovisnosti koja se oslanja na modul Graphql-java-annotations:
com.graphql-java graphql-java-anotacije 3.0.3
Također implementiramo HTTP knjižnicu kako bismo olakšali postavljanje u našoj aplikaciji. Koristit ćemo Ratpack (iako bi se mogao implementirati i s Vert.x, Spark, Dropwizard, Spring Boot itd.).
Uvezimo i ovisnost Ratpack:
io.ratpack ratpack-core 1.4.6
4.3. Provedba
Stvorimo naš primjer: jednostavni API koji korisnicima nudi "CRUDL" (Stvori, preuzmi, ažuriraj, izbriši i popis). Prvo, kreirajmo svoje Korisnik POJO:
@GraphQLName ("user") javna klasa Korisnik {@GraphQLField private Long id; @GraphQLField ime privatnog niza; @GraphQLField privatni niz e-pošte; // izostavljeni getteri, postavljači, konstruktori i pomoćne metode}
U ovom POJO možemo vidjeti @GraphQLName ("korisnik") anotacija, kao pokazatelj da GraphQL mapira ovu klasu zajedno sa svakim poljem označenim s @GraphQLField.
Dalje ćemo stvoriti UserHandler razred. Ova klasa nasljeđuje od odabrane knjižnice HTTP konektora (u našem slučaju, Ratpack) metodu rukovatelja, koja će upravljati i pozivati GraphQL-ove Razrješivač značajka. Dakle, preusmjeravanje zahtjeva (JSON nosivosti) na odgovarajući upit ili operaciju mutacije:
@Override public void handle (Context context) baca izuzetak {context.parse (Map.class). Then (payload -> {Map parameters = (Map) payload.get ("parameters"); ExecutionResult execuResult = graphql .execute (payload) .get (SchemaUtils.QUERY) .toString (), null, this, parametri); Map result = new LinkedHashMap (); if (ExecuResult.getErrors (). isEmpty ()) {result.put (SchemaUtils.DATA, ExecuResult. getData ());} else {result.put (SchemaUtils.ERRORS, ExecuResult.getErrors ()); LOGGER.warning ("Pogreške:" + Execution Result.getErrors ());} context.render (json (rezultat)); }); }
Sada će klasa koja će podržavati operacije upita, tj. UserQuery. Kao što je spomenuto, svim metodama koje dohvaćaju podatke sa poslužitelja do klijenta upravlja ova klasa:
@GraphQLName ("query") javna klasa UserQuery {@GraphQLField javni statični korisnik retrieveUser (DataFetchingEnvironment env, @NotNull @GraphQLName ("id") String id) {// return user} @GraphQLField javni statički popis popisaUser (DataFetchingEnvironment en // povratak popisa korisnika}}
Slično kao UserQuery, sada stvaramo UserMutation, koji će upravljati svim operacijama koje namjeravaju promijeniti neke zadane podatke pohranjene na strani poslužitelja:
@GraphQLName ("mutacija") javna klasa UserMutation {@GraphQLField javni statički korisnik createUser (DataFetchingEnvironment env, @NotNull @GraphQLName ("name") Ime niza, @NotNull @GraphQLName ("email") String e-pošta) {// stvoriti korisnika informacije}}
Vrijedno je primijetiti napomene u obje UserQuery i UserMutation klase: @GraphQLName ("upit") i @GraphQLName („mutacija“). Te se bilješke koriste za definiranje operacija upita i mutacije.
Pomoću GraphQL-java poslužitelja koji može izvoditi operacije upita i mutacije, možemo koristiti sljedeća JSON opterećenja za testiranje zahtjeva klijenta prema poslužitelju:
- Za operaciju CREATE:
{"query": "mutacija ($ name: String! $ email: String!) {createUser (name: $ name email: $ email) {id name email age}}", "parametri": {"name": " John "," email ":" [e-mail zaštićen] "}}
Kao odgovor poslužitelja za ovu operaciju:
{"data": {"createUser": {"id": 1, "name": "John", "email": "[email zaštićen]"}}}
- Za operaciju RETRIEVE:
{"query": "query ($ id: String!) {retrieveUser (id: $ id) {name email}}", "parametri": {"id": 1}}
Kao odgovor poslužitelja za ovu operaciju:
{"data": {"retrieveUser": {"name": "John", "email": "[email protected]"}}}
GraphQL pruža značajke koje klijent može prilagoditi odgovoru. Dakle, u posljednjoj operaciji RETRIEVE koja je korištena kao primjer, umjesto vraćanja imena i e-pošte, možemo, na primjer, vratiti samo e-poštu:
{"query": "query ($ id: String!) {retrieveUser (id: $ id) {email}}", "parametri": {"id": 1}}
Dakle, povratne informacije s GraphQL poslužitelja vratit će samo tražene podatke:
{"data": {"retrieveUser": {"email": "[email protected]"}}}
5. Zaključak
GraphQL je jednostavan i prilično atraktivan način za smanjivanje složenosti između klijenta / poslužitelja kao alternativni pristup REST API-ima.
Kao i uvijek, primjer je dostupan u našem GitHub spremištu.