GraphQL标准的Java实现graphql-java概述

GraphQL标准提供了多种主流编程语言的实现,本文介绍其中的Java实现graphql-java。所谓GraphQL标准的实现,就是一个GraphQL服务器的实现,通过一组软件组件,以支持请求的解析、验证和执行GraphQL查询。

graphql-java就是GraphQL标准的Java语言实现之一,当前最新版本是8.0。在Maven项目中配置如下:


    com.graphql-java
    graphql-java
    8.0


本文主要介绍graphql-java的核心的GraphQL Schema定义。

1. GraphQL Schema

就类似于数据库服务器要响应用户对数据库的访问,首先要定义数据库Schema一样。GraphQL服务器要是响应用户对REST数据的查询请求,也要定义一个描述服务数据的结构,就是GraphQL Schema。

为了定义GraphQL Schema,graphql-java提供了如下两种定义的方式:

  • 代码中编程定义动态GraphQL Schema
GraphQLObjectType fooType = newObject()
    .name("Ci")
    .field(newFieldDefinition()
            .name("product_number")
            .type(GraphQLString))
    .build();

如代码所示,运行中创建了新类型Ci,并为其定义了属性product_number,该属性的类型为Scalar的GraphQLString。

  • 使用SDL (Schema Definition Language)在独立的资源文件中定义静态GraphQL Schema

创建src/main/resources/myschema.graphqls文件,定义类型Ci如下:

type Ci {
    product_number: String
}

这里,为了示例,两种方式定义的GraphQL Schema完全等价。

实际上定义完整的GraphQL Schema还有具体的语法,请参考创建GraphQL Schema。

2. DataFetcher/TypeResolver

GraphQL Schema中的每个字段类型,都关联一个DataFetcher(在Node.js实现或Python实现中被称为resolver函数),用以为GraphQL Schema中的字段类型获取数据。数据源可以是数据库或REST服务,并将数据表示为Java POJO对象。DataFetcher对象可以直接读取Java POJO对象的属性,再使用Jackson或GSON转换为JSON格式的数据。

DataFetcher pnDataFetcher = new DataFetcher() {
    @Override
    public Object get(DataFetchingEnvironment environment) {
        Map response = fetchPnFromDatabase(environment.getArgument("product_number"));
		List errors = ((List)response.get("errors")).stream()
			.map(MyMapGraphQLError::new)
			.collect(Collectors.toList());
		return new DataFetcherResult(response.get("data"), errors);
    }
};

GraphQLObjectType objectType = newObject()
        .name("Ci")
        .field(newFieldDefinition()
                .name("product_number")
                .type(GraphQLString)
                .dataFetcher(pnDataFetcher))
        .build();


注意,这里的dataFetcher()方法的使用。

与DataFetcher获取数据的作用相似,TypeResolver提供了更强大的功能,能够根据获取的数据转换为对应的Schema中定义的字段类型,这对面向接口的编程有很大的意义。在一个获取数据的方法中,定义返回的类型是接口,而实际返回可能是实现该接口的任何对象,根据获取的数据转换为对应的对象,返回即可。


3. Runtime Wiring

创建完毕GraphQL Schema还只是开始,还要将其应用在GraphQL服务器上。这就类似于定义数据库结构的SDL脚本已经准备就绪,但是真正在数据库服务器上执行后才生效。

在GraphQL服务器上真正执行GraphQL Schema使其运行起来,是通过Runtime Wiring,这样才能够得到一个可执行的GraphQL Schema。典型代码如下:

File schemaFile = loadSchema("myschema.graphqls");

SchemaParser schemaParser = new SchemaParser();
TypeDefinitionRegistry typeRegistry = schemaParser.parse(schemaFile);

RuntimeWiring wiring = RuntimeWiring.newRuntimeWiring()....build();
SchemaGenerator schemaGenerator = new SchemaGenerator();
GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeRegistry, wiring);

4. GraphQL服务

已经有了完整的可响应请求的GraphQL Schema,现在就运行起来吧。

GraphQL build = GraphQL.newGraphQL(graphQLSchema).build();

5. Execution请求GraphQL服务

1) 请求参数

在请求应用中,可以直接将请求参数以字符串的形式传递给GraphQL服务,如下所示:

ExecutionResult executionResult = build.execute("query { hero { name } }");

也可以先构建ExecutionInput对象(适合复杂的请求参数),然后再传递给GraphQL服务,如下所示:

ExecutionInput executionInput = ExecutionInput.newExecutionInput().query("query { hero { name } }")
        .build();
ExecutionResult executionResult = build.execute(executionInput);

2)处理结果

GraphQL服务的响应结果在data中,如果出错则在

executionResult.getData().toString();
List errors = executionResult.getErrors();

如果要将得到的响应数据序列化为JSON格式,为了完全兼容GraphQL标准,建议首先将响应结果进行规范化转换,然后再调用Jackson或GSON等JSON库进行JSON格式转换。

Map toSpecificationResult = executionResult.toSpecification();
doWithJson(toSpecificationResult);

这里只讨论了同步的请求,异步请求可以参考其文档。

参考链接:

https://github.com/graphql-java/graphql-java

http://graphql-java.readthedocs.io/en/latest/


你可能感兴趣的:(Micro,Services)