GraphQL和spring boot的结合例子
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。
