您的当前位置:首页正文

Graphql 实战:Load Schema From IDL

来源:花图问答

更新日志

日期 更新内容 备注
2017-11-20 新建文章 初版
2017-11-20 23:47 一种更加智能的load方式可以参考 update-11-20

导入

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
}

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,这样可读性更强,更好维护。