GraphQL和spring boot的结合例子

发表于2019-05-08,长度1806, 127个单词, 5分钟读完
Flag Counter

GraphQL是Facebook开发的一套微服务API,用于代替REST方案。

在REST中,通过不同的http行为区分用户动作,及时相同的uri搭配不同的行为,内部逻辑也差别迥异。GraphQL(Graph + Query Language)中,由客户端决定自己需要的数据:这就是客户端发送请求服务端响应数据的原因。《RPC vs REST vs GraphQL》中介绍了REST和GraphQL的差别。官方首页的动态展示会让你更了解GraphQL。


来看一个例子,这是一个使用spring boot搭建的简易网上书店。代码在我的github库graphql上。

其中的Java代码都很简单,应该能看懂。注意schema文件,graphQL通过schema的定义获取数据并返回。schema文件要放在类路径下,所以我们放在resources目录下。

服务启动后,控制器内有一个被@PostConstruct标记的方法,这个方法加载schema文件。对文件的解析当天是graphQL实现的,这是它的核心逻辑。

  @PostConstruct
  public void loadSchema() throws IOException {
    // get the schema
    File schemaFile = schemaResource.getFile();
    // parse schema
    TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(schemaFile);
    RuntimeWiring wiring = buildRuntimeWiring();
    GraphQLSchema schema = new SchemaGenerator().makeExecutableSchema(typeRegistry, wiring);
    graphQL = GraphQL.newGraphQL(schema).build();
  }

对于不同类型的获取要注册获取类,上面代码中调用的buildRuntimeWiring()里面就是注册过程:

  private RuntimeWiring buildRuntimeWiring() {
    return RuntimeWiring.newRuntimeWiring()
        .type("Query",
            typeWiring -> typeWiring.dataFetcher("allBooks", allBookDataFetcher).dataFetcher("book", bookDataFetcher))
        .build();
  }

allBooks和book被分别绑定到了不同的fetcher上,它们都是在schema中定义的。

当post访问地址/getAllBooks的时候,需要把查询类型传进来,所以请求体应该类似这样:

query{ allBooks{bookId,bookName }} 

graphQL看到查询的是“allBooks”就会调用对应的fetcher,也就是AllBookDataFetcher。我们看一下它的代码:

@Component
public class AllBookDataFetcher implements DataFetcher<List<Book>> {
    @Autowired
    private BookRepository repository;

    @Override
    public List<Book> get(DataFetchingEnvironment environment) {
        return repository.findAll();
    }
}

代码极其简单,graphQL会调用get方法返回对应的请求字段。上面我们只写了bookId,bookName,所以返回的就是这两个字段。


GraphQL是REST之外的另一套选项,但不意味着比REST更强。目前来说REST还是流行得多,用起来也方便。当你的后台需要给不同的前端设备返回不同格式的数据时,可以考虑graphQL。

Written on May 8, 2019
分类: dev, 标签: springboot graphql
如果你喜欢,请赞赏! davelet