Úvod do GraphQL

1. Prehľad

GraphQL je dotazovací jazyk, ktorý vytvoril Facebook za účelom vytvárania klientských aplikácií na základe intuitívnej a flexibilnej syntaxe na opis ich požiadaviek na údaje a interakcií.

Jednou z hlavných výziev pri tradičných hovoroch REST je neschopnosť klienta požadovať prispôsobenú (obmedzenú alebo rozšírenú) množinu údajov. Vo väčšine prípadov, keď klient požaduje informácie zo servera, získa buď všetky, alebo žiadne z polí.

Ďalším problémom je práca a údržba viacerých koncových bodov. S rastúcou platformou sa ich počet bude zvyšovať. Preto musia klienti často požadovať údaje z rôznych koncových bodov.

Pri vytváraní servera GraphQL je potrebné mať iba jednu adresu URL na načítanie a mutáciu všetkých údajov. Klient teda môže požiadať o množinu údajov zaslaním reťazca dotazu s popisom toho, čo chce, na server.

2. Základná nomenklatúra GraphQL

Pozrime sa na základnú terminológiu GraphQL.

  • Dopyt: je operácia iba na čítanie požadovaná na server GraphQL
  • Mutácia: je operácia čítania a zápisu požadovaná na server GraphQL
  • Rezolver: V GraphQL sa Rezolver je zodpovedný za mapovanie operácie a kódu bežiaceho na backende, ktorý je zodpovedný za vybavenie žiadosti. Je obdobou back-endu MVC v aplikácii RESTFul
  • Typ: A Typ definuje tvar dát odozvy, ktoré je možné vrátiť zo servera GraphQL, vrátane polí, ktoré majú od ostatných hrany Typy
  • Vstup: ako Typ, ale definuje tvar vstupných údajov, ktoré sa odosielajú na server GraphQL
  • Skalárny: je primitiv Typ, ako je a String, Int, Boolovský, Plavák, atď
  • Rozhranie: Rozhranie bude ukladať názvy polí a ich argumenty, aby z nich mohli dediť objekty GraphQL, čo zabezpečí použitie konkrétnych polí
  • Schéma: V GraphQL schéma riadi dotazy a mutácie a definuje, čo je možné vykonať na serveri GraphQL

2.1. Načítava sa schéma

Existujú dva spôsoby načítania schémy na server GraphQL:

  1. používaním GraphQL's Interface Definition Language (IDL)
  2. pomocou jedného z podporovaných programovacích jazykov

Ukážme si príklad pomocou IDL:

zadajte používateľ {firstName: String}

Teraz príklad definície schémy pomocou kódu Java:

GraphQLObjectType userType = newObject () .name ("User") .field (newFieldDefinition () .name ("firstName") .type (GraphQLString)) .build ();

3. Jazyk definície rozhrania

Interface Definition Language (IDL) alebo Schema Definition Language (SDL) je najstručnejší spôsob, ako určiť schému GraphQL. Syntax je dobre definovaná a bude prijatá v oficiálnej špecifikácii GraphQL.

Napríklad vytvorme schému GraphQL pre používateľa / e-maily by sme mohli určiť takto:

schéma {query: QueryType} enum Pohlavie {MALE FEMALE} typ Používateľ {id: String! firstName: Reťazec! priezvisko: Reťazec! createdAt: DateTime! vek: Int! @ predvolené (hodnota: 0) pohlavie: [pohlavie]! e-maily: [E-mail!]! @relation (name: "Emails")} typ Email {id: String! email: Reťazec! predvolené: Int! @ predvolené (hodnota: 0) používateľ: používateľ @vzťah (meno: „E-maily“)}

4. GraphQL-java

GraphQL-java je implementácia založená na špecifikácii a referenčnej implementácii JavaScriptu. Upozorňujeme, že na správne fungovanie je potrebná najmenej Java 8.

4.1. Anotácie GraphQL-java

GraphQL tiež umožňuje používať anotácie Javy na generovanie definície svojej schémy bez toho, aby bol použitý štandardný kód vytvorený použitím tradičného prístupu IDL.

4.2. Závislosti

Na vytvorenie nášho príkladu začnime najskôr importovať požadovanú závislosť, ktorá sa spolieha na modul Graphql-java-annotations:

 com.graphql-java graphql-java-anotácie 3.0.3 

Na uľahčenie nastavenia v našej aplikácii implementujeme aj knižnicu HTTP. Budeme používať Ratpack (aj keď by to mohlo byť implementované aj s Vert.x, Spark, Dropwizard, Spring Boot atď.).

Importujme tiež závislosť Ratpack:

 io.ratpack ratpack-core 1.4.6 

4.3. Implementácia

Vytvorme si náš príklad: jednoduché API, ktoré poskytuje používateľom „CRUDL“ (Create, Retrieve, Update, Delete, and List). Najprv si vytvorme našu Používateľ POJO:

@GraphQLName („užívateľ“) verejná trieda Používateľ {@GraphQLField private Long id; @GraphQLField súkromné ​​meno reťazca; @GraphQLField private String email; // vynechávajúci, nastavujúci, konštruktor a pomocné metódy}

V tomto POJO môžeme vidieť @GraphQLName („používateľ“) anotácia, ako indikácia, že táto trieda je mapovaná GraphQL spolu s každým poľom s anotáciou @GraphQLField.

Ďalej vytvoríme UserHandler trieda. Táto trieda dedí z vybranej knižnice konektorov HTTP (v našom prípade Ratpack) metódu obsluhy, ktorá bude spravovať a vyvolávať GraphQL Rezolver vlastnosť. Presmerovanie požiadavky (užitočné zaťaženie JSON) na správnu operáciu dotazu alebo mutácie:

@Override public void handle (Context context) throws Exception {context.parse (Map.class) .then (payload -> {Map parameters = (Map) payload.get ("parameters"); ExecutionResult executionResult = graphql .execute (payload .get (SchemaUtils.QUERY) .toString (), null, this, parameters); Výsledok mapy = new LinkedHashMap (); if (executionResult.getErrors (). isEmpty ()) {result.put (SchemaUtils.DATA, executionResult. getData ());} else {result.put (SchemaUtils.ERRORS, executionResult.getErrors ()); LOGGER.warning ("Chyby:" + executionResult.getErrors ());} context.render (json (result)); }); }

Teraz trieda, ktorá bude podporovať operácie dotazu, t. J. UserQuery. Ako už bolo spomenuté, všetky metódy, ktoré načítavajú údaje zo servera do klienta, sú spravované touto triedou:

@GraphQLName ("dopyt") verejná trieda UserQuery {@GraphQLField public static User retrieveUser (DataFetchingEnvironment env, @NotNull @GraphQLName ("id") reťazec id) {// návratový používateľ} @GraphQLField verejný statický zoznam listUsers (DataFetchingEnvironment env) { // návratový zoznam používateľov}}

Podobne ako UserQuery, teraz tvoríme UserMutation, ktorý bude riadiť všetky operácie, ktoré majú v úmysle zmeniť niektoré dané dáta uložené na strane servera:

@GraphQLName ("mutácia") verejná trieda UserMutation {@GraphQLField public static Používateľ createUser (DataFetchingEnvironment env, @NotNull @GraphQLName ("name") Názov reťazca, @NotNull @GraphQLName ("email") String email) {// vytvoriť používateľa informácie}}

Stojí za povšimnutie anotácie v obidvoch UserQuery a UserMutation triedy: @GraphQLName („dopyt“) a @GraphQLName („mutácia“). Tieto anotácie sa používajú na definovanie operácií dotazu a mutácií.

Pretože server GraphQL-java dokáže spustiť operácie dotazovania a mutácie, môžeme na otestovanie požiadavky klienta na serveri použiť nasledujúce užitočné súbory JSON:

  • Pre operáciu CREATE:
{"query": "mutácia ($ name: String! $ email: String!) {createUser (name: $ name email: $ email) {id name email age}}", "parameters": {"name": " John "," email ":" [e-mail chránený] "}} 

Ako odpoveď servera na túto operáciu:

{"data": {"createUser": {"id": 1, "name": "John", "email": "[chránený e-mailom]"}}}
  • Pre operáciu RETRIEVE:
{"query": "query ($ id: String!) {retrieveUser (id: $ id) {name email}}", "parameters": {"id": 1}}

Ako odpoveď servera na túto operáciu:

{"data": {"retrieveUser": {"name": "John", "email": "[chránený e-mailom]"}}}

GraphQL poskytuje funkcie, ktoré si klient môže prispôsobiť podľa svojich reakcií. Takže v poslednej operácii RETRIEVE použitej ako príklad môžeme namiesto vrátenia mena a e-mailu napríklad vrátiť iba e-mail:

{"query": "query ($ id: String!) {retrieveUser (id: $ id) {email}}", "parameters": {"id": 1}}

Takže návratové informácie zo servera GraphQL vrátia iba požadované údaje:

{"data": {"retrieveUser": {"email": "[chránený e-mailom]"}}}

5. Záver

GraphQL je ľahký a celkom atraktívny spôsob minimalizácie zložitosti medzi klientom / serverom ako alternatívny prístup k rozhraniam REST API.

Ako vždy, príklad je k dispozícii v našom úložisku GitHub.