GraphQL入門總體創(chuàng)建教程
簡(jiǎn)介
因?yàn)槟壳白龅捻?xiàng)目查詢提供的接口都使用GraphQL替代典型的REST API,所以有必要去對(duì)它進(jìn)行了解和源碼的閱讀。本篇主要大致了解下GraphQL。
一種用于API的查詢語(yǔ)言,讓你的請(qǐng)求數(shù)據(jù)不多不少。前端按需獲取,后端動(dòng)態(tài)返回(不需要的數(shù)據(jù)不會(huì)返回甚至不會(huì)查庫(kù)),對(duì)比起典型的REST API將更加靈活,后端代碼提供可選能力。如果增加新的字段應(yīng)用不想處理這部分?jǐn)?shù)據(jù)可以不用區(qū)分版本。
后端確定哪些接口行為是被允許的,前端按需獲取數(shù)據(jù),讓你的請(qǐng)求數(shù)據(jù)不多不少。
詳細(xì)的介紹可以參考官方首頁(yè)配合動(dòng)圖更加清晰。
簡(jiǎn)單示例
最好使用Spring Initializr去創(chuàng)建一個(gè)新的項(xiàng)目,不會(huì)產(chǎn)生一些沖突。
maven依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.graphql-java.tutorial</groupId>
<artifactId>book-details</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>book-details</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.graphql-java/graphql-java -->
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java</artifactId>
<version>11.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.graphql-java/graphql-java-spring-boot-starter-webmvc -->
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-spring-boot-starter-webmvc</artifactId>
<version>1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>26.0-jre</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>central</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<layout>default</layout>
<!-- 是否開啟發(fā)布版構(gòu)件下載 -->
<releases>
<enabled>true</enabled>
</releases>
<!-- 是否開啟快照版構(gòu)件下載 -->
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
Schema
在src/main/resources中創(chuàng)建schema.graphqls文件:
type Query {
bookById(id: ID): Book
}
type Book {
id: ID
name: String
pageCount: Int
author: Author
}
type Author {
id: ID
firstName: String
lastName: String
}
可以看到定義了一個(gè)bookById查詢,用于根據(jù)id查詢書籍,書籍中包含id、name、pageCount、author屬性,其中author是一個(gè)復(fù)合類型所以定義了type Author。
上面顯示的用于描述schema的特定于域的語(yǔ)言稱為schema定義語(yǔ)言或SDL。更多細(xì)節(jié)可以在這里找到。
解析schema并關(guān)聯(lián)對(duì)應(yīng)的fetchers
一旦我們有了這個(gè)文件,我們需要通過(guò)讀取文件并解析它并且添加代碼來(lái)為它獲取數(shù)據(jù)使它“栩栩如生”。
package com.graphqljava.tutorial.bookdetails;
import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.net.URL;
import static graphql.schema.idl.TypeRuntimeWiring.newTypeWiring;
@Component
public class GraphQLProvider {
private GraphQL graphQL;
/**
* 注入GraphQL實(shí)例,GraphQL Java Spring適配器將使用GraphQL實(shí)例使我們的schema可用,通過(guò)Http-使用默認(rèn)的"/graphql"url路徑
*
* @return
*/
@Bean
public GraphQL graphQL() {
return graphQL;
}
@PostConstruct
public void init() throws IOException {
//使用Resources讀取graphqls文件
URL url = Resources.getResource("schema.graphqls");
//拿到graphqls文件內(nèi)容
String sdl = Resources.toString(url, Charsets.UTF_8);
GraphQLSchema graphQLSchema = buildSchema(sdl);
this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();
}
@Autowired
GraphQLDataFetchers graphQLDataFetchers;
/**
* 創(chuàng)建GraphQLSchema實(shí)例:解析schema并關(guān)聯(lián)fetcher
*
* @param sdl
* @return
*/
private GraphQLSchema buildSchema(String sdl) {
TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);
RuntimeWiring runtimeWiring = buildWiring();
SchemaGenerator schemaGenerator = new SchemaGenerator();
return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);
}
/**
* 根據(jù)層級(jí)去關(guān)聯(lián)fetcher構(gòu)建RuntimeWiring。最外層為Query可以提供bookById所需參數(shù)。第二層為Book-經(jīng)過(guò)第一層獲得的,可以為author提供所需參數(shù)。
*
* @return
*/
private RuntimeWiring buildWiring() {
return RuntimeWiring.newRuntimeWiring()
.type(newTypeWiring("Query")
.dataFetcher("bookById", graphQLDataFetchers.getBookByIdDataFetcher()))
.type(newTypeWiring("Book")
.dataFetcher("author", graphQLDataFetchers.getAuthorDataFetcher()))
.build();
}
}
package com.graphqljava.tutorial.bookdetails;
import com.google.common.collect.ImmutableMap;
import graphql.schema.DataFetcher;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Component
public class GraphQLDataFetchers {
/**
* books靜態(tài)數(shù)據(jù)
*/
private static List<Map<String, String>> books = Arrays.asList(
ImmutableMap.of("id", "book-1",
"name", "Harry Potter and the Philosopher's Stone",
"pageCount", "223",
"authorId", "author-1"),
ImmutableMap.of("id", "book-2",
"name", "Moby Dick",
"pageCount", "635",
"authorId", "author-2"),
ImmutableMap.of("id", "book-3",
"name", "Interview with the vampire",
"pageCount", "371",
"authorId", "author-3")
);
/**
* autors靜態(tài)數(shù)據(jù)
*/
private static List<Map<String, String>> authors = Arrays.asList(
ImmutableMap.of("id", "author-1",
"firstName", "Joanne",
"lastName", "Rowling"),
ImmutableMap.of("id", "author-2",
"firstName", "Herman",
"lastName", "Melville"),
ImmutableMap.of("id", "author-3",
"firstName", "Anne",
"lastName", "Rice")
);
/**
* bookById的fetcher,這里只是簡(jiǎn)單的通過(guò)靜態(tài)數(shù)據(jù)進(jìn)行篩選,具體生產(chǎn)使用sql進(jìn)行查詢
*
* @return
*/
public DataFetcher getBookByIdDataFetcher() {
return dataFetchingEnvironment -> {
// 獲得查詢篩選參數(shù)
String bookId = dataFetchingEnvironment.getArgument("id");
return books
.stream()
.filter(book -> book.get("id").equals(bookId))
.findFirst()
.orElse(null);
};
}
/**
* 第二層author fetcher
*
* @return
*/
public DataFetcher getAuthorDataFetcher() {
return dataFetchingEnvironment -> {
//獲得上級(jí)對(duì)象
Map<String, String> book = dataFetchingEnvironment.getSource();
//根據(jù)上級(jí)對(duì)象找到關(guān)聯(lián)id(相當(dāng)于外鍵)
String authorId = book.get("authorId");
return authors
.stream()
.filter(author -> author.get("id").equals(authorId))
.findFirst()
.orElse(null);
};
}
}
DataFetchers
對(duì)于GraphQL Java服務(wù)器來(lái)說(shuō),最重要的概念可能是DataFetcher:DataFetcher在執(zhí)行查詢時(shí)獲取一個(gè)字段的數(shù)據(jù)。
GraphQL Java在執(zhí)行查詢時(shí),會(huì)為查詢中遇到的每個(gè)字段調(diào)用相應(yīng)的DataFetcher。DataFetcher是函數(shù)接口,函數(shù)具有一個(gè)參數(shù)為DataFetchingEnvironment類型。
public interface DataFetcher<T> {
T get(DataFetchingEnvironment dataFetchingEnvironment) throws Exception;
}
Default DataFetchers
如上我們實(shí)現(xiàn)了兩個(gè)DataFetchers。如上所述,如果你不指定一個(gè),PropertyDataFetcher則是被默認(rèn)使用。比如上面的例子中Book.id,Book.name,Book.pageCount,Author.id,Author.firstName和Author.lastName都有一個(gè)PropertyDataFetcher與之關(guān)聯(lián)。
PropertyDataFetcher嘗試以多種方式查找Java對(duì)象的屬性。如果是java.util.Map,簡(jiǎn)單的通過(guò)key查找。這對(duì)我們來(lái)說(shuō)非常好,因?yàn)閎ook和author Maps的keys與schema中指定的字段相同。
總體創(chuàng)建過(guò)程

資料
Getting started with Spring Boot
以上就是GraphQL入門總體創(chuàng)建教程的詳細(xì)內(nèi)容,更多關(guān)于GraphQL創(chuàng)建教程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Mybatis事務(wù)如何跟Spring結(jié)合(數(shù)據(jù)庫(kù)事務(wù)特性和Spring事務(wù)管理源碼)
MyBatis與Spring的事務(wù)結(jié)合主要是通過(guò)Spring的事務(wù)管理和MyBatis的數(shù)據(jù)庫(kù)操作來(lái)實(shí)現(xiàn)的,在本文中,我們將從數(shù)據(jù)庫(kù)事務(wù)特性和Spring事務(wù)管理源碼兩個(gè)角度來(lái)分析MyBatis事務(wù)如何與Spring結(jié)合到一起的原理,感興趣的朋友一起看看吧2024-01-01
Java使用PDFBox實(shí)現(xiàn)操作PDF文檔
這篇文章主要為大家詳細(xì)介紹了Java如何使用PDFBox實(shí)現(xiàn)操作PDF文檔,例如添加本地圖片、添加網(wǎng)絡(luò)圖片、圖片寬高自適應(yīng)、圖片水平垂直居中對(duì)齊等功能,需要的可以了解下2024-03-03
Future與FutureTask接口實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了Future與FutureTask接口實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
SPRINGMVC JSON數(shù)據(jù)交互如何實(shí)現(xiàn)
這篇文章主要介紹了SPRINGMVC JSON數(shù)據(jù)交互如何實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06

