作者: 一字马胡
转载标志 【2017-11-20】
更新日志
日期 | 更新内容 | 备注 |
---|---|---|
2017-11-20 | 新建文章 | 初版 |
2017-11-20 23:47 | 一种更加智能的load方式可以参考GraphQLEndpoint | update-11-20 |
导入
在文章GraphQL初探:一种强大的DSQL中大致介绍了Graphql这种神奇的新技术,并且文章中附带了一个Graphql-Java的demo,该demo使用Spring-Boot驱动运行,而demo中创建Schema的方式有点麻烦,需要写很多相似的代码来创建我们需要的Schema,当我们的Model比较少的时候还可以接受,但是当我们的Model非常多的时候,使用这种类似于“硬编码”的方式创建Schema的方式就不太合适了,其实Graphql还提供了例外一种创建Schema的方式,那就是IDL文件的方式,我们只需要写好IDL文件,从文件中就可以加载我们需要的Schema,这种方式相对于第一种方式来说会节省大量的代码,并且可以更加直观的设计我们的Schema,官方也主推使用IDL文件的方式来创建Schema,本文接着第一篇文章,介绍如何使用IDL文件创建我们需要的Schema。
Action
首先,下面先展示一段IDL文件内容:
schema {
query: QueryType
}
type QueryType {
person(name: String!): Person
}
type Person {
id: Int!
name: String!
friends: [Person]
roles: [Role]
}
type Role {
id: Int!
name: String!
}
首先需要定义我们的Graphql类型,有两种可选的类型:
schema {
query: Query,
mutation: Mutation
}
类似于: label:Type 组成的语句前者代表的是标志,而后者是类型,如果后面有感叹号,说明这个字段是必须的,否则是可选的。关于Graphql的类型,可以参考Graphql Type,下面展示了一些Graphql提供的类型:
Scalar
- GraphQLString
- GraphQLBoolean
- GraphQLInt
- GraphQLFloat
- GraphQLID
- GraphQLLong
- GraphQLShort
- GraphQLByte
- GraphQLFloat
- GraphQLBigDecimal
- GraphQLBigInteger
Object
IDL Example:
type SimpsonCharacter {
name: String
mainCharacter: Boolean
}
Java Example:
GraphQLObjectType simpsonCharacter = newObject()
.name("SimpsonCharacter")
.description("A Simpson character")
.field(newFieldDefinition()
.name("name")
.description("The name of the character.")
.type(GraphQLString))
.field(newFieldDefinition()
.name("mainCharacter")
.description("One of the main Simpson characters?")
.type(GraphQLBoolean))
.build();
Interface
IDL Example:
interface ComicCharacter {
name: String;
}
Java Example:
GraphQLInterfaceType comicCharacter = newInterface()
.name("ComicCharacter")
.description("A abstract comic character.")
.field(newFieldDefinition()
.name("name")
.description("The name of the character.")
.type(GraphQLString))
.build();
Union
IDL Example:
interface ComicCharacter {
name: String;
}
Java Example:
GraphQLUnionType PetType = newUnionType()
.name("Pet")
.possibleType(CatType)
.possibleType(DogType)
.typeResolver(new TypeResolver() {
@Override
public GraphQLObjectType getType(TypeResolutionEnvironment env) {
if (env.getObject() instanceof Cat) {
return CatType;
}
if (env.getObject() instanceof Dog) {
return DogType;
}
return null;
}
})
.build();
Enum
IDL Example:
enum Color {
RED
GREEN
BLUE
}
Java Example:
GraphQLEnumType colorEnum = newEnum()
.name("Color")
.description("Supported colors.")
.value("RED")
.value("GREEN")
.value("BLUE")
.build();
ObjectInputType
IDL Example:
input Character {
name: String
}
Java Example:
GraphQLInputObjectType inputObjectType = newInputObject()
.name("inputObjectType")
.field(newInputObjectField()
.name("field")
.type(GraphQLString))
.build();
具体的运用需要结合实际的场景。现在回头来看上面贴出的IDL文件,可以看到他有两个Model(Person和Role),对于Person来说,它有四个字段,id和name字段是必须要提供的,而friends和roles事可选的,它们的类型在后面可以看到。对于Role来说,它的两个字段都是必须的,分别为id和name,类型分别为int和String。下面来介绍如何从这个文件中获取到Schema。假设我们把这个文件命名为schema.graphqls,下面的代码展示了如何加载IDL文件并且从文件内容创建Schema的方法:
public GraphQLSchema graphQLSchema() throws IOException {
SchemaParser schemaParser = new SchemaParser();
SchemaGenerator schemaGenerator = new SchemaGenerator();
String schemaFileContent = readSchemaFileContent();
TypeDefinitionRegistry typeRegistry = schemaParser.parse(schemaFileContent);
RuntimeWiring wiring = buildRuntimeWiring();
return schemaGenerator.makeExecutableSchema(typeRegistry, wiring);
}
private String readSchemaFileContent() throws IOException {
ClassPathResource classPathResource = new ClassPathResource("schema.graphqls");
try (InputStream inputStream = classPathResource.getInputStream()) {
return CharStreams.toString(new InputStreamReader(inputStream, Charsets.UTF_8));
}
}
private RuntimeWiring buildRuntimeWiring() {
return RuntimeWiring.newRuntimeWiring()
.type("QueryType",
typeWiring -> typeWiring
.dataFetcher("person", new DataFetcher() {
@Override
public Object get(DataFetchingEnvironment environment) {
return null;
}
})
).build();
}
获得Schema之后,我们就可以进行查询了。
结语
本文内容比较单薄,可以看成是对第一篇介绍Graphql文章的一点补充,当然,更多的关于Graphql的内容将会持续总结出来,本文的内容集中在使用IDL文件来创建我们需要的Graphql Schema,如果我们的Model比较多并且比较复杂的时候,应该首选使用IDL的方式来创建我们需要的Schema,这样可读性更强,更好维护。