微信公众号:九极客

欢迎星标关注九极客,一起探讨技术与架构!

大家的点赞、收藏和评论很重要,如文章对您有帮助还请转发支持下,谢谢!

图片
图注:大少公众号

随着应用程序和服务的不断发展,数据需求往往会经历多次变化。为了应对这种变化,传统的RESTful API可能需要频繁地进行版本更新,而GraphQL作为一种灵活且高度可定制的查询语言,可以更好地适应数据需求的变化。本文将深入探讨在Spring Boot中如何使用GraphQL来灵活处理数据需求的变化。

图片

GraphQL简介

GraphQL是一种由Facebook开发的API查询语言,它允许客户端明确指定其数据需求,由服务端返回相应的结果。GraphQL的核心优势在于:

  • 灵活性:客户端可以精确指定所需数据,避免了过度获取或缺乏的问题。

  • 单一请求:通过单一请求获取多个资源的数据,减少了网络开销。

  • 强类型:使用强类型系统定义数据模型,提高了数据的可靠性和安全性。

图片

Spring Boot中集成GraphQL 重试    错误原因

2.1 添加依赖

在Spring Boot项目中集成GraphQL,可以使用graphql-spring-boot-starter简化配置。

<span>&lt;<span>dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span>&lt;<span>groupId</span>&gt;</span>com.graphql-java-kickstart<span>&lt;/<span>groupId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span>&lt;<span>artifactId</span>&gt;</span>graphql-spring-boot-starter<span>&lt;/<span>artifactId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span>&lt;<span>version</span>&gt;</span>11.1.0<span>&lt;/<span>version</span>&gt;</span><br><span>&lt;/<span>dependency</span>&gt;</span><br>

2.2 定义GraphQL Schema 重试    错误原因

定义GraphQL的Schema包括类型、查询和变更等。

<span>//&nbsp;定义类型</span><br><span>public</span>&nbsp;<span><span>class</span>&nbsp;<span>Book</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span>private</span>&nbsp;String&nbsp;title;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span>private</span>&nbsp;String&nbsp;author;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;省略其他属性和方法</span><br>}<br><br><span>//&nbsp;定义查询</span><br><span>@Component</span><br><span>public</span>&nbsp;<span><span>class</span>&nbsp;<span>GraphQLQuery</span>&nbsp;<span>implements</span>&nbsp;<span>GraphQLQueryResolver</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span><span>public</span>&nbsp;Book&nbsp;<span>getBookById</span><span>(String&nbsp;id)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;查询数据库或其他数据源获取书籍信息</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;省略具体实现</span><br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br><span>//&nbsp;定义Schema</span><br><span>@Configuration</span><br><span>public</span>&nbsp;<span><span>class</span>&nbsp;<span>GraphQLConfig</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span>@Bean</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span><span>public</span>&nbsp;GraphQLScalarType&nbsp;<span>dateTime</span><span>()</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;定义日期时间类型</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;省略具体实现</span><br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span>@Bean</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span><span>public</span>&nbsp;GraphQLSchema&nbsp;<span>graphQLSchema</span><span>(GraphQLObjectType&nbsp;query)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>return</span>&nbsp;GraphQLSchema.newSchema()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.query(query)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.build();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span>@Bean</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span><span>public</span>&nbsp;GraphQLObjectType&nbsp;<span>query</span><span>(GraphQLQuery&nbsp;graphQLQuery)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;定义查询类型</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>return</span>&nbsp;GraphQLObjectType.newObject()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.name(<span>"Query"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.field(newFieldDefinition()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.name(<span>"getBookById"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.type(GraphQLTypeReference.typeRef(<span>"Book"</span>))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.argument(arg&nbsp;-&gt;&nbsp;arg.name(<span>"id"</span>).type(Scalars.GraphQLID))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.dataFetcher(graphQLQuery::getBookById))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;省略其他查询字段</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.build();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br>

2.3 处理GraphQL请求

在Spring Boot应用中处理GraphQL请求,并提供相应的数据。

<span>@RestController</span><br><span>@RequestMapping</span>(<span>"/graphql"</span>)<br><span>public</span>&nbsp;<span><span>class</span>&nbsp;<span>GraphQLController</span>&nbsp;</span>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span>@Autowired</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span>private</span>&nbsp;GraphQL&nbsp;graphQL;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span>@PostMapping</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span><span>public</span>&nbsp;ResponseEntity&lt;Object&gt;&nbsp;<span>executeQuery</span><span>(@RequestBody&nbsp;String&nbsp;query)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExecutionResult&nbsp;executionResult&nbsp;=&nbsp;graphQL.execute(query);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>return</span>&nbsp;ResponseEntity.ok(executionResult.toSpecification());<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br>

图片

处理数据需求的变化

3.1 新增字段

当应用需要新增字段时,GraphQL可以轻松支持。只需在相应的类型中添加新字段,并在Schema中声明即可。

<span>//&nbsp;在Book类型中新增字段</span><br><span>public</span>&nbsp;<span><span>class</span>&nbsp;<span>Book</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span>private</span>&nbsp;String&nbsp;title;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span>private</span>&nbsp;String&nbsp;author;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span>private</span>&nbsp;<span>int</span>&nbsp;pageCount;&nbsp;&nbsp;<span>//&nbsp;新增字段</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;省略其他属性和方法</span><br>}<br><br><span>//&nbsp;在Schema中声明新增字段</span><br><span>@Bean</span><br><span><span>public</span>&nbsp;GraphQLObjectType&nbsp;<span>query</span><span>(GraphQLQuery&nbsp;graphQLQuery)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span>return</span>&nbsp;GraphQLObjectType.newObject()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.name(<span>"Query"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.field(newFieldDefinition()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.name(<span>"getBookById"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.type(GraphQLTypeReference.typeRef(<span>"Book"</span>))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.argument(arg&nbsp;-&gt;&nbsp;arg.name(<span>"id"</span>).type(Scalars.GraphQLID))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.dataFetcher(graphQLQuery::getBookById))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;省略其他查询字段</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.build();<br>}<br>

3.2 移除字段

如果某个字段不再需要,同样可以轻松地从Schema中移除,而不会影响其他字段。

<span>//&nbsp;在Book类型中移除字段</span><br><span>public</span>&nbsp;<span><span>class</span>&nbsp;<span>Book</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span>private</span>&nbsp;String&nbsp;title;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span>private</span>&nbsp;String&nbsp;author;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;省略其他属性和方法</span><br>}<br><br><span>//&nbsp;在Schema中移除字段</span><br><span>@Bean</span><br><span><span>public</span>&nbsp;GraphQLObjectType&nbsp;<span>query</span><span>(GraphQLQuery&nbsp;graphQLQuery)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span>return</span>&nbsp;GraphQLObjectType.newObject()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.name(<span>"Query"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.field(newFieldDefinition()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.name(<span>"getBookById"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.type(GraphQLTypeReference.typeRef(<span>"Book"</span>))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.argument(arg&nbsp;-&gt;&nbsp;arg.name(<span>"id"</span>).type(Scalars.GraphQLID))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.dataFetcher(graphQLQuery::getBookById))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;省略其他查询字段</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.build();<br>}<br>

3.3 新增查询

如果需要新增查询,只需在Schema中添加新的查询字段。

<span>@Bean</span><br><span><span>public</span>&nbsp;GraphQLObjectType&nbsp;<span>query</span><span>(GraphQLQuery&nbsp;graphQLQuery)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span>return</span>&nbsp;GraphQLObjectType.newObject()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.name(<span>"Query"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.field(newFieldDefinition()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.name(<span>"getBookById"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.type(GraphQLTypeReference.typeRef(<span>"Book"</span>))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.argument(arg&nbsp;-&gt;&nbsp;arg.name(<span>"id"</span>).type(Scalars.GraphQLID))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.dataFetcher(graphQLQuery::getBookById))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.field(newFieldDefinition()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.name(<span>"getBooksByAuthor"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.type(<span>new</span>&nbsp;GraphQLList(GraphQLTypeReference.typeRef(<span>"Book"</span>)))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.argument(arg&nbsp;-&gt;&nbsp;arg.name(<span>"author"</span>).type(Scalars.GraphQLString))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.dataFetcher(graphQLQuery::getBooksByAuthor))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;省略其他查询字段</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.build();<br>}<br>

图片

安全性考虑

在处理数据需求变化时,要特别注意安全性的问题。合适的认证和授权机制可以确保只有合法用户能够访问敏感信息。

图片

结论

通过本文的介绍,我们深入了解了在Spring Boot中如何使用GraphQL应对数据需求的变化。GraphQL的灵活性和强类型系统使得我们能够更容易地处理新增、移除字段以及新增查询等变化,而无需频繁更新API版本。在实际应用中,根据具体场景合理使用GraphQL,可以使应用更加灵活且易于维护。


感谢星标关注九极客,欢迎留言讨论!

图片