Az első lépések a GraphQL és a Spring Boot használatával

1. Bemutatkozás

A GraphQL egy viszonylag új koncepció a Facebook-tól, amelyet a REST for Web API-k alternatívájaként számláznak.

Ez a cikk bemutatja a GraphQL szerver beállítását a Spring Boot használatával, hogy hozzá lehessen adni a meglévő alkalmazásokhoz, vagy újakban használhatók.

2. Mi az GraphQL?

A hagyományos REST API-k a szerver által kezelt erőforrások koncepciójával működnek. Ezeket az erőforrásokat bizonyos szokásos módon, a különféle HTTP igék követésével lehet manipulálni. Ez nagyon jól működik mindaddig, amíg az API-nk megfelel az erőforrás-koncepciónak, de gyorsan szétesik, ha eltérnünk kell tőle.

Ez akkor is szenved, ha az ügyfélnek egyszerre több erőforrásról van szüksége adatokra. Például egy blogbejegyzés és a megjegyzések kérése. Általában ezt úgy oldják meg, hogy vagy az ügyfélnek több kérést kell elküldenie, vagy azzal, hogy a kiszolgáló olyan extra adatokat szolgáltat, amelyekre nem mindig van szükség, ami nagyobb válaszmérethez vezet.

A GraphQL mindkét problémára megoldást kínál. Lehetővé teszi az ügyfél számára, hogy pontosan meghatározza, milyen adatokra van szükség, ideértve az alárendelt erőforrások egyetlen kérésben történő navigálását is, és lehetővé teszi több lekérdezés egyetlen kérelemben történő megadását.

Ez sokkal RPC-s módon is működik, megnevezett lekérdezéseket és mutációkat használva a kötelező kötelező műveletsor helyett. Ez úgy működik, hogy a vezérlőt oda helyezzük, ahová tartozik, az API-fejlesztő megadva, hogy mi lehetséges, és az API-fogyasztó, mi a kívánt.

Például egy blog engedélyezheti a következő lekérdezést:

lekérdezés {legfrissebbPosts (szám: 10, eltolás: 0) {id címkategória szerző {id név miniatűr}}}

Ez a lekérdezés:

  • kérje a tíz legfrissebb bejegyzést
  • minden bejegyzéshez kérje az azonosítót, a címet és a kategóriát
  • minden hozzászóláshoz kérje a szerzőt, visszaadva az azonosítót, a nevet és az indexképet

Egy hagyományos REST API-ban ehhez vagy 11 kérésre van szükség - 1 a hozzászólásokhoz és 10 a szerzőkhöz -, vagy a szerző adatait is fel kell tüntetniük a bejegyzés részleteiben.

2.1. GraphQL sémák

A GraphQL szerver az API-t leíró sémát tár fel. Ez a séma típusdefiníciókból áll. Mindegyik típusnak van egy vagy több mezője, amelyek mindegyike nulla vagy több argumentumot tartalmaz, és egy adott típust ad vissza.

A grafikon abból áll, ahogy ezek a mezők egymásba vannak ágyazva. Ne feledje, hogy a gráfnak nem kell aciklusosnak lennie - a ciklusok tökéletesen elfogadhatóak -, de irányított. Vagyis az ügyfél eljuthat egy mezőből a gyermekei közé, de automatikusan nem juthat vissza a szülőhöz, kivéve, ha a séma ezt kifejezetten meghatározza.

Egy blog GraphQL sémájának egy példája a következő meghatározásokat tartalmazhatja, amelyek leírják a Bejegyzést, a Bejegyzés Szerzőjét és a legfrissebb bejegyzéseket a blogon.

type Post {id: ID! cím: Húr! szöveg: Húr! kategória: Húr szerző: Szerző! } típus Szerző {id: ID! név: Húr! indexkép: Karakterláncok: [Hozzászólás]! } # A Query {legújabbPosts (count: Int, offset: Int) alkalmazástípus gyökérlekérdezése: [Post]! } # A Mutation {typePost (cím: String !, szöveg: String !, kategória: String) alkalmazástípus gyökérmutációja: Posta! }

A "!" néhány név végén azt jelzi, hogy ez egy nem nullázható típus. Bármely típus, amelynek nincs ilyen, null lehet a kiszolgáló válaszában. A GraphQL szolgáltatás ezeket helyesen kezeli, lehetővé téve számunkra, hogy biztonságosan kérjünk nullázható típusú gyermekmezőket.

A GraphQL szolgáltatás a szokásos mezők használatával magát a sémát is kiteszi, így minden ügyfél idő előtt lekérdezheti a séma definícióját.

Ez lehetővé teheti az ügyfél számára, hogy automatikusan észlelje a séma változását, és lehetővé tegye az ügyfelek számára, amelyek dinamikusan alkalmazkodnak a séma működéséhez. Ennek egyik hihetetlenül hasznos példája a későbbiekben tárgyalt GraphiQL eszköz, amely lehetővé teszi számunkra, hogy bármilyen GraphQL API-val együttműködjünk.

3. A GraphQL Spring Boot Starter bemutatása

A Spring Boot GraphQL Starter fantasztikus módot kínál arra, hogy egy GraphQL szervert nagyon rövid idő alatt fusson. A GraphQL Java Tools könyvtárral együtt csak a szolgáltatásunkhoz szükséges kódot kell megírnunk.

3.1. A szolgáltatás beállítása

Ehhez csak a helyes függőségekre van szükségünk:

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

A Spring Boot automatikusan felveszi ezeket, és beállítja a megfelelő kezelőket az automatikus működéshez.

Alapértelmezés szerint ez kiteszi a GraphQL szolgáltatást a / graphql alkalmazásunk végpontja, és elfogadja a GraphQL hasznos terhet tartalmazó POST kéréseket. Ez a végpont testreszabható a alkalmazás.tulajdonságok fájl, ha szükséges.

3.2. A séma megírása

A GraphQL Tools könyvtár a GraphQL Schema fájlok feldolgozásával működik a megfelelő struktúra felépítéséhez, majd speciális babokat vezet hozzá ehhez a struktúrához. A Spring Boot GraphQL indító automatikusan megtalálja ezeket a sémafájlokat.

Ezeket a fájlokat a „” kiterjesztéssel kell menteni.graphqls”És bárhol jelen lehet az osztályúton. Ezekből a fájlokból is rendelkezhetünk annyival, amennyit csak kívánunk, így a sémát szükség szerint modulokra oszthatjuk fel.

Az egyik követelmény az, hogy pontosan egy gyökér lekérdezésnek és legfeljebb egy gyökérmutációnak kell lennie. Ez nem osztható fel fájlokra, ellentétben a sémával. Ez korlátozza magát a GraphQL séma definíciót, és nem a Java implementációt.

3.3. Root Query Resolver

A gyökérlekérdezéshez speciális babokat kell megadni a Spring kontextusban, hogy kezeljék a gyökérlekérdezés különféle mezőit. A sémadefiníciótól eltérően nincs megkötés, hogy a gyökér lekérdezés mezõinek csak egyetlen Spring babja legyen.

Az egyetlen követelmény a bab végrehajtása GraphQLQueryResolver és hogy a séma gyökér lekérdezésének minden mezőjében van egy módszer ugyanazon névvel az osztályok egyikében.

public class Query megvalósítja a GraphQLQueryResolver {private PostDao postDao; public list getRecentPosts (int count, int offset) {return postsDao.getRecentPosts (count, offset); }}

A módszer nevének a következők egyikének kell lennie, ebben a sorrendben:

  1. is - csak akkor, ha a mező típusú Logikai
  2. kap

A metódusnak olyan paraméterekkel kell rendelkeznie, amelyek megfelelnek a GraphQL séma bármely paraméterének, és adott esetben megadhat egy végső típusú paramétert is DataFetchingEnvironment.

A metódusnak a megfelelő visszatérési típust is vissza kell adnia a GraphQL sémában szereplő típushoz, amint láthatjuk. Minden egyszerű típus - Karakterlánc, Int, List, stb. - egyenértékű Java típusokkal használható, és a rendszer csak automatikusan feltérképezi őket.

A fentiek definiálták a módszert getRecentPosts amelyet a GraphQL bármilyen lekérdezésének kezelésére fogunk használni Legutóbbi hozzászólások mező a korábban definiált sémában.

3.4. Bab használata a típusok ábrázolásához

A GraphQL szerver minden összetett típusát egy Java komponens képviseli - akár a root lekérdezésből, akár a struktúra bárhonnan máshonnan lett betöltve. Ugyanazon Java osztálynak mindig ugyanazt a GraphQL típust kell képviselnie, de az osztály neve nem szükséges.

A Java-babon belüli mezők a mező neve alapján közvetlenül a GraphQL válasz mezőire fognak térképezni.

public class Hozzászólás {private String id; privát húr cím; privát húr kategória; private String authorId; }

A Java bab minden olyan mezőjét vagy metódusát, amely nem kapcsolódik a GraphQL sémához, figyelmen kívül hagyja, de nem okoz problémát. Ez fontos a terepi megoldók működéséhez.

Például a mező authorId itt nem felel meg semminek a korábban meghatározott sémánkban, de a következő lépéshez használható lesz.

3.5. Terepi felbontók a komplex értékekhez

Előfordul, hogy egy mező értéke nem triviális a betöltéshez. Ez magában foglalhatja az adatbázis-keresést, az összetett számításokat vagy bármi mást. A GraphQL Tools rendelkezik egy mezőfelbontó koncepcióval, amelyet erre a célra használnak. Ezek olyan tavaszi babok, amelyek értékeket szolgáltathatnak az adatbab helyett.

A mezőfeloldó bármely olyan bab a Spring Contextben, amelynek neve ugyanaz, mint az adatbabbal, utótaggal Megoldó, és ez megvalósítja a GraphQLResolver felület. A terepi felbontókészülék metódusai ugyanazokat a szabályokat követik, mint az adatbab esetében, de első paraméterként magukat az adatbabokat is megadják.

Ha egy mezőfeloldónak és az adatrésznek is vannak módszerei ugyanarra a GraphQL mezőre, akkor a mezőfelbontó elsőbbséget élvez.

public class A PostResolver megvalósítja a GraphQLResolver {private AuthorDao authorDao; public Author getAuthor (Post post) {return authorDao.getAuthorById (post.getAuthorId ()); }}

Fontos, hogy ezek a terepi felbontók a tavaszi kontextusból vannak betöltve. Ez lehetővé teszi számukra, hogy bármilyen más tavasszal kezelt babgal együtt dolgozzanak - például DAO-kkal.

Fontos, ha az ügyfél nem kér mezőt, akkor a GraphQL Server soha nem fogja megtenni a munkát. Ez azt jelenti, hogy ha az ügyfél beolvassa a Bejegyzést, és nem kéri a Szerzőt, akkor a getAuthor () A fenti metódust soha nem hajtják végre, és a DAO hívást soha nem hajtják végre.

3.6. Nullable Értékek

A GraphQL séma szerint az egyes típusok érvénytelenek, mások pedig nem.

Ez a Java kódban kezelhető közvetlenül nullértékek, de ugyanúgy az új értékek használatával Választható A Java 8-ból származó típus itt közvetlenül használható semmissé váló típusokhoz, és a rendszer az értékekkel helyesen fog cselekedni.

Ez nagyon hasznos, mivel azt jelenti, hogy a Java kódunk nyilvánvalóan megegyezik a metódefiníciókból származó GraphQL sémával.

3.7. Mutációk

Eddig minden, amit tettünk, az adatok lekéréséről szólt a szerverről. A GraphQL képes arra is, hogy mutációk segítségével frissítse a szerveren tárolt adatokat.

A kód szempontjából nincs semmi oka annak, hogy egy lekérdezés nem tudja megváltoztatni az adatokat a szerveren. Könnyen írhatunk olyan lekérdező megoldókat, amelyek elfogadják az argumentumokat, új adatokat mentenek el, és visszaadják ezeket a változásokat. Ez meglepő mellékhatásokat okoz az API kliensek számára, és rossz gyakorlatnak számít.

Helyette, Mutációkkal kell tájékoztatni az ügyfelet arról, hogy ez megváltoztatja a tárolt adatokat.

A mutációkat a Java kódban definiáljuk megvalósító osztályok használatával GraphQLMutationResolver ahelyett GraphQLQueryResolver.

Ellenkező esetben ugyanazok a szabályok érvényesek, mint a lekérdezésekre. A mutációs mezőből származó visszatérési értéket ezután pontosan ugyanúgy kezeljük, mint a Query mezőből, lehetővé téve a beágyazott értékek lekérését is.

public class Mutation implementálja a GraphQLMutationResolver {private PostDao postDao; public Post writePost (karakterlánc címe, karakterlánc szövege, karakterlánc kategóriája) {return postDao.savePost (cím, szöveg, kategória); }}

4. A GraphiQL bemutatása

A GraphQL rendelkezik egy GraphiQL nevű társeszközzel is. Ez egy olyan felhasználói felület, amely képes kommunikálni bármely GraphQL szerverrel, és lekérdezéseket és mutációkat tud végrehajtani ellene. Letölthető verziója létezik Electron alkalmazásként, és innen letölthető.

Automatikusan beilleszthető a GraphiQL webes verziója is alkalmazásunkba, hozzáadva a GraphiQL Spring Boot Starter függőségét:

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

Ez csak akkor fog működni, ha a GraphQL API-t az alapértelmezett végponton tároljuk / graphql bár önálló alkalmazásra lesz szükség, ha nem ez a helyzet.

5. Összefoglalás

A GraphQL egy nagyon izgalmas új technológia, amely potenciálisan forradalmasíthatja a webes API-k fejlesztésének módját.

A Spring Boot GraphQL Starter és a GraphQL Java Tools könyvtárak kombinációja hihetetlenül megkönnyíti ennek a technológiának az új vagy meglévő Spring Boot alkalmazásokhoz történő hozzáadását.

A kódrészletek megtalálhatók a GitHubon.