在上一篇的java实现中,分享了使用GraphQL的基本流程,接下来分享一下在Spring Boot中对GraphQL的应用
首先创建一个Spring Boot的项目
<?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.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.clc</groupId>
<artifactId>boot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>boot</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-web</artifactId>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java</artifactId>
<version>15.0</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
接下来就是创建一个schema的文件,来写graphql的定义,这里还用之前的例子。resources下创建一个user.graphqls。
#对应的User定义如下
schema {
#定义查询
query: UserQuery
}
#定义查询类型
type UserQuery {
#指定对象以及参数类型
queryUser : User
queryUserById(id:ID) : User
}
#定义对象
type User {
#!表示非空
id:ID!
name:String
age:Int
card:Card
}
type Card {
cardNumber:String
userId:ID
}
package com.clc.boot.bean;
import lombok.Data;
/**
* ClassName: User<br/>
* Description: <br/>
* date: 2019/6/28 10:38 AM<br/>
*
* @author chengluchao
* @since JDK 1.8
*/
@Data
public class User {
private int age;
private long id;
private String name;
private Card card;
public User(int age, long id, String name, Card card) {
this.age = age;
this.id = id;
this.name = name;
this.card = card;
}
public User(int age, long id, String name) {
this.age = age;
this.id = id;
this.name = name;
}
}
package com.clc.boot.bean;
import lombok.Data;
/**
* ClassName: Card<br/>
* Description: <br/>
* date: 2019/6/28 3:25 PM<br/>
*
* @author chengluchao
* @since JDK 1.8
*/
@Data
public class Card {
private String cardNumber;
private Long userId;
public Card(String cardNumber, Long userId) {
this.cardNumber = cardNumber;
this.userId = userId;
}
}
package com.clc.boot.graphql;
import com.clc.boot.bean.User;
import com.clc.boot.bean.Card;
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.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
/**
* 实现功能:将GraphQL对象载入待Spring容器,并且完成GraphQL对象初始化的功能
*
* @author chengluchao
*/
@Component
public class GraphQLProvider {
private GraphQL graphQL;
@Bean
public GraphQL graphQL() {
return graphQL;
}
/**
* 加载schema
*
* @throws IOException
*/
@PostConstruct
public void init() throws IOException {
File file = ResourceUtils.getFile("classpath:user.graphqls");
GraphQLSchema graphQLSchema = buildGraphQLSchema(file);
this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();
}
private GraphQLSchema buildGraphQLSchema(File file) {
TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(file);
GraphQLSchema graphQLSchema = new SchemaGenerator().makeExecutableSchema(typeRegistry, buildWiring());
return graphQLSchema;
}
private GraphQLSchema buildSchema(String sdl) {
TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);
RuntimeWiring runtimeWiring = buildWiring();
SchemaGenerator schemaGenerator = new SchemaGenerator();
return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);
}
/**
* 业务实现,demo版
* 如果是开发实战,这一点的设计是重点,需要考虑如何根据graphql中定义的方法来执行java代码
*
* @return
*/
private RuntimeWiring buildWiring() {
RuntimeWiring wiring = RuntimeWiring.newRuntimeWiring()
.type("UserQuery", builder ->
builder.dataFetcher("queryUserById", environment -> {
Long id = Long.parseLong(environment.getArgument("id"));
Card card = new Card("123456", id);
return new User(18, id, "user0" + id, card);
})
)
.build();
return wiring;
}
}
接下来是GraphQL的入口:
package com.clc.boot.controller;
import graphql.ExecutionResult;
import graphql.GraphQL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* ClassName: GraphQLController<br/>
* Description: <br/>
* date: 2019/6/28 5:38 PM<br/>
*
* @author chengluchao
* @since JDK 1.8
*/
@RequestMapping("graphql")
@Controller
public class GraphQLController {
@Autowired
private GraphQL graphQL;
@RequestMapping("query")
@ResponseBody
public Object query(@RequestParam("query") String query) {
ExecutionResult result = this.graphQL.execute(query);
return result.toSpecification();
}
}
测试:
127.0.0.1:8080/graphql/query?query={ user: queryUserById(id:15){id,name,age,card{cardNumber,userId}}}
{
"data": {
"user": {
"id": "15",
"name": "user015",
"age": 18,
"card": {
"cardNumber": "123456",
"userId": "15"
}
}
}
}
源码地址:https://gitee.com/chengluchao/graphql-clc/tree/master/graphql-springboot
这里实现了graphql在spring-boot中的应用,由于解析graphql到业务执行还不够自动化,所以此例子还是一个demo级别
CLC