美文网首页Java技术GraphQL技术程序员
Graphql 实战:Load Schema From IDL

Graphql 实战:Load Schema From IDL

作者: 一字马胡 | 来源:发表于2017-11-20 23:33 被阅读112次

作者: 一字马胡
转载标志 【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,这样可读性更强,更好维护。

相关文章

网友评论

    本文标题:Graphql 实战:Load Schema From IDL

    本文链接:https://www.haomeiwen.com/subject/fgzbvxtx.html