SpringBoot GraphQL
基于spring boot的web项目快速应用。
graphql-java的官方文档:Getting started with GraphQL Java and Spring Boot https://www.graphql-java.com/tutorials/getting-started-with-spring-boot/,提供了相关依赖用以快速配置,不建议使用这个库及相关配置方式来搭建脚手架,在实际开发中,业务比较复杂的时候,会导致需要配置的业务代码比较多也比较繁琐,相对下面这种方式,代码复杂性比较高。
这里提供一种更灵活快捷的方式,在spring boot项目中快速应用开发。使用的依赖也和上面官方提供的都不一样,请注意区分。

快速开始

创建spring boot工程

通过Spring Initializr https://start.spring.io/快速搭建,选的jdk版本及spring boot版本,如下所示,其它版本未做兼容性测试。
Spring Boot   GraphQL整合开发 - 图1
点击下方的Generate按钮:
Spring Boot   GraphQL整合开发 - 图2
打开工程结构如下,将application.properties删除了替换成applicaiton.yml:
Spring Boot   GraphQL整合开发 - 图3

引入相关依赖

pom.xml配置如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.4.6</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.xuxd</groupId>
  12. <artifactId>graphql.demo</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>graphql.demo</name>
  15. <description>GraphQL Demo project for Spring Boot</description>
  16. <properties>
  17. <java.version>1.8</java.version>
  18. <maven.compiler.source>1.8</maven.compiler.source>
  19. <maven.compiler.target>1.8</maven.compiler.target>
  20. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  21. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  22. <lombok.version>1.18.20</lombok.version>
  23. <graphql-java-tools.version>11.0.1</graphql-java-tools.version>
  24. <gson.version>2.8.7</gson.version>
  25. </properties>
  26. <dependencies>
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-starter</artifactId>
  30. </dependency>
  31. <dependency>
  32. <groupId>org.springframework.boot</groupId>
  33. <artifactId>spring-boot-starter-web</artifactId>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.springframework.boot</groupId>
  37. <artifactId>spring-boot-starter-test</artifactId>
  38. <scope>test</scope>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.projectlombok</groupId>
  42. <artifactId>lombok</artifactId>
  43. <version>${lombok.version}</version>
  44. <scope>provided</scope>
  45. </dependency>
  46. <dependency>
  47. <groupId>com.graphql-java-kickstart</groupId>
  48. <artifactId>graphql-java-tools</artifactId>
  49. <version>${graphql-java-tools.version}</version>
  50. </dependency>
  51. <dependency>
  52. <groupId>com.google.code.gson</groupId>
  53. <artifactId>gson</artifactId>
  54. <version>${gson.version}</version>
  55. </dependency>
  56. </dependencies>
  57. <build>
  58. <plugins>
  59. <plugin>
  60. <groupId>org.springframework.boot</groupId>
  61. <artifactId>spring-boot-maven-plugin</artifactId>
  62. </plugin>
  63. </plugins>
  64. </build>
  65. </project>

初始化GraphQL实例

创建一个GraphQL实例并将其注册到spring容器中,代码如下:
创建一个GraphQLProvider类:

  1. @Component
  2. public class GraphQLProvider {
  3. private GraphQL graphQL;
  4. @Autowired
  5. private IItemService itemService;
  6. @Bean
  7. public GraphQL graphQL() {
  8. return graphQL;
  9. }
  10. @PostConstruct
  11. public void init() throws IOException {
  12. GraphQLSchema graphQLSchema = SchemaParser.newParser()
  13. .file("graphql/base.graphqls")
  14. .resolvers(new Query(), new Mutation())
  15. .file("graphql/item.graphqls")
  16. .resolvers(new ItemResolver(itemService))
  17. // .file("book.graphqls")
  18. // .resolvers(new BookResolver()) //其它定义照上面的示例,继续增加
  19. .build().makeExecutableSchema();
  20. this.graphQL = graphQL.newGraphQL(graphQLSchema).build();
  21. }
  22. }

关于*.graphqls或者对应的Resolver如ItemResolver,这里只是作了微调整,相关代码如下:
base.grqphqls

  1. schema {
  2. # 查询
  3. query: Query
  4. # 更新
  5. mutation: Mutation
  6. }
  7. type Query {
  8. version: String
  9. }
  10. type Mutation {
  11. version: String
  12. }

item.graphqls

  1. # 定义一个查询类型
  2. extend type Query {
  3. queryItemList: ItemList # 定义查询项目列表
  4. queryById(id: ID): Item
  5. }
  6. extend type Mutation {
  7. updateName(param: Param): Item
  8. }
  9. # 定义项目字段
  10. type Item {
  11. id: ID!
  12. code: String!
  13. name: String!
  14. }
  15. type ItemList {
  16. itemList: [Item!]! #获取项目列表
  17. total: Int! # 获取项目总数
  18. }
  19. input Param {
  20. id: ID!
  21. name: String!
  22. }

ItemResolver

  1. public class ItemResolver implements GraphQLQueryResolver, GraphQLMutationResolver {
  2. private IItemService itemService;
  3. public ItemResolver(IItemService itemService) {
  4. this.itemService = itemService;
  5. }
  6. // 对应item.graphqls里的queryItemList
  7. public ItemList queryItemList() {
  8. return itemService.queryItemList();
  9. }
  10. public Item queryById(Long id) {
  11. return itemService.queryById(id);
  12. }
  13. public Item updateName(Param param) {
  14. return itemService.updateName(param);
  15. }
  16. }

相关业务代码比较多,就不一一贴了。

提供API

需要暴露一个接口来接收请求,并作相关处理,也只需提供一个接口即可。因此创建一个Controller:GraphqlController.

  1. @RestController
  2. @RequestMapping("/graphql")
  3. @Log
  4. public class GraphqlController {
  5. @Autowired
  6. private GraphQL graphQL;
  7. @PostMapping
  8. public Object execute(@RequestBody GraphqlRequest request) {
  9. ExecutionInput executionInput = ExecutionInput.newExecutionInput()
  10. .query(request.getQuery())
  11. .variables(request.getVariables())
  12. .build();
  13. Map<String, Object> result = new HashMap<>();
  14. ExecutionResult executionResult = graphQL.execute(executionInput);
  15. List<GraphQLError> errors = executionResult.getErrors();
  16. if (errors != null && !errors.isEmpty()) {
  17. result.put("errors", errors);
  18. return result;
  19. }
  20. return executionResult.getData();
  21. }
  22. }

到这一步,其实基本功能都已配置完成,可以启动项目进行相关测试了。
整个项目的代码结构如下,尽量用了一个比较常规的web项目结构(controller,service,dao等):
Spring Boot   GraphQL整合开发 - 图4

测试

示例中总共提供了3个接口,两个查询一个更新,分别进行测试:

  1. ItemList queryItemList();
  2. Item queryById(Long id);
  3. Item updateName(Param param);

查询所有项目列表(只获取每个项目的编码和名称,以及列表总数):

Spring Boot   GraphQL整合开发 - 图5

根据ID查询,获取项目的id和名称

Spring Boot   GraphQL整合开发 - 图6

更新指定ID的项目名称

项目Id为1编码为test的项目修改为“java项目”
Spring Boot   GraphQL整合开发 - 图7
再查询一下,可以看到结果更新了:
Spring Boot   GraphQL整合开发 - 图8