简介
是一种查询语言,类似前端与后端之间通过sql语言进行交互。用类似json的语言来查询需要的数据。
如在以下查询语句
{
bookById(id: "1") {
id
name
pageCount
author {
name
}
}
}
可以得到一下结果
{
"data": {
"bookById": {
"id": "1",
"name": "风雪追击",
"pageCount": 233,
"author": {
"name": "东野圭吾"
}
}
}
}
maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java</artifactId>
<version>11.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-spring-boot-starter-webmvc</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>26.0-jre</version>
</dependency>
定义schema
上面的查询语句我们事先定义了一下schema,放置在src/main/resources/schema.graphqls
type Query {
bookById(id: ID): Book
authors:[Author]
books:[Book]
authorAndBooks:[Author]
}
type Book {
id: ID
name: String
pageCount: Int
author: Author
}
type Author {
id: ID
name: String
books:[Book]
}
其中类型为Query的表示为查询,类似CURD中的R;除了Query还有Mutation来表示对数据进行修改,相当于CURD中的CUD操作。在schema中定义了4跳query语句如上所示。我们还定义了Book和Author的类型,其中Book中包含一个Author,Author中包含Book的列表。
定义GraphQLProvider
GraphQLProvider类将会创建一个GraphQL的实例,这里通过@Bean的方式暴露出去可以通过/graphql的url访问到(由依赖graphql-java-spring-boot-starter-webmvc实现的功能)
@Component
public class GraphQLProvider {
private GraphQL graphQL;
@Bean
public GraphQL graphQL() {
return graphQL;
}
@Autowired
GraphQLDataFetchers graphQLDataFetchers;
@PostConstruct
public void init() throws IOException {
URL url = Resources.getResource("schema.graphqls");
String sdl = Resources.toString(url, Charsets.UTF_8);
GraphQLSchema graphQLSchema = buildSchema(sdl);
this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();
}
private GraphQLSchema buildSchema(String sdl) {
TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);
RuntimeWiring runtimeWiring = buildWiring();
SchemaGenerator schemaGenerator = new SchemaGenerator();
return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);
}
private RuntimeWiring buildWiring() {
Map<String, DataFetcher> map = new HashMap<String,DataFetcher>();
map.put("bookById",graphQLDataFetchers.getBookByIdDataFetcher());
map.put("books",graphQLDataFetchers.getBooksDataFetcher());
map.put("authors",graphQLDataFetchers.getAuthorsDataFetcher());
return RuntimeWiring.newRuntimeWiring()
.type(newTypeWiring("Query")
.dataFetchers(map))
.type(newTypeWiring("Book")
.dataFetcher("author", graphQLDataFetchers.getAuthorDataFetcher())
.dataFetcher("pageCount",graphQLDataFetchers.getPageCountDataFetcher()))
.type(newTypeWiring("Author")
.dataFetcher("books",graphQLDataFetchers.getBooksByAUthorDataFetcher()))
.build();
}
}
DataFetchers
GraphQL在执行查询时,是通过Datafetcher来获取一个字段的数据。DataFetcher是一个接口
public interface DataFetcher<T> {
T get(DataFetchingEnvironment var1) throws Exception;
}
新建一个类用于存放所有的datafetcher(小型项目)
@Component
public class GraphQLDataFetchers {
private static List<Map<String, String>> books = Arrays.asList(
ImmutableMap.of("id", "1",
"name", "风雪追击",
"totalPages", "233",
"authorId", "a1"),
ImmutableMap.of("id", "4",
"name", "解忧杂货店",
"totalPages", "342",
"authorId", "a1"),
ImmutableMap.of("id", "2",
"name", "达芬奇密码",
"totalPages", "635",
"authorId", "a2"),
ImmutableMap.of("id", "3",
"name", "大秦帝国",
"totalPages", "371",
"authorId", "a3")
);
private static List<Map<String, String>> authors = Arrays.asList(
ImmutableMap.of("id", "a1",
"name", "东野圭吾"),
ImmutableMap.of("id", "a2",
"name", "丹布朗"),
ImmutableMap.of("id", "a3",
"name", "孙皓晖")
);
public DataFetcher getBookByIdDataFetcher() {
return dataFetchingEnvironment -> {
String bookId = dataFetchingEnvironment.getArgument("id");
return books
.stream()
.filter(book -> book.get("id").equals(bookId))
.findFirst()
.orElse(null);
};
}
public DataFetcher getAuthorDataFetcher() {
return dataFetchingEnvironment -> {
Map<String,String> book = dataFetchingEnvironment.getSource();
String authorId = book.get("authorId");
return authors
.stream()
.filter(author -> author.get("id").equals(authorId))
.findFirst()
.orElse(null);
};
}
public DataFetcher getBooksByAUthorDataFetcher(){
return dataFetchingEnvironment -> {
Map<String,String> author = dataFetchingEnvironment.getSource();
String authorId = author.get("id");
return books.stream().filter(book->book.get("authorId").equals(authorId)).toArray();
};
}
public DataFetcher getAuthorTotalCountDataFetcher(){
return dataFetchingEnvironment -> {
Map<String,Object> author = dataFetchingEnvironment.getSource();
String authorId = author.get("id").toString();
return books.stream().filter(book->book.get("authorId").equals(authorId))
.collect(Collectors.summingInt(map->Integer.parseInt(map.get("totalPages"))));
};
}
public DataFetcher getAuthorsDataFetcher(){
return dataFetchingEnvironment->{
return authors;
};
}
public DataFetcher getBooksDataFetcher(){
return dataFetchingEnvironment -> {
return books;
};
}
public DataFetcher getPageCountDataFetcher() {
return dataFetchingEnvironment -> {
Map<String,String> book = dataFetchingEnvironment.getSource();
return book.get("totalPages");
};
}
}
验证
可以使用graphql-playground工具来进行验证。我电脑的版本是macos10.15.4,使用1.8.9可以运行,1.8.10则会报错,使用前需要在顶栏输入http://localhost:8080/graphql,然后在左边输入查询语句,右边就能得到查询结果。
网友评论