Graphql 实战:Load Schema From IDL File

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容