graphql

“ GraphQL是API的查询语言,是用于使用现有数据完成这些查询的运行时。 GraphQL为您的API中的数据提供了完整且易于理解的描述,使客户能够准确地询问他们所需的内容,仅此而已,使随着时间的推移更容易开发API并启用强大的开发人员工具。”

–来自https://graphql.org/

任何已经建立了可供多个消费者使用的REST服务的人,例如其他服务,网站或移动设备,都会知道很难建立一个能够满足所有需求的完美端点。 对于所有这些特殊情况,您通常最终都会获得相同服务的变体:)

现在,我们都知道我们应该只使用HATEOAS …,它在我的TODO列表中(承诺!),直到我偶然发现GraphQL为止 。

因此,在这篇博客文章中,我将解释如何轻松地将GraphQL添加到现有的JAX-RS应用程序中。

示例项目

Github中提供了示例项目,并且非常容易上手。

git clone https://github.com/phillip-kruger/membership.git
cd membership
mvn clean install

这将使用示例应用程序http:// localhost:8080 / membership /来启动fatjar wildfly-swarm

高水平

该示例是基本的成员资格服务,您可以在其中获得所有成员或特定成员。 您可以添加,编辑和删除成员。

该应用程序是典型的JAX-RS,CDI,EJB,JPA,Bean验证Java EE应用程序,我们将添加一个新的GraphQL端点。

GraphQL部分使用以下库:

  • graphql-java
  • graphql-java-servlet
  • graphQL-spqr
  • 石墨烯

我添加来将现有的JAX-RS公开为GraphQL的唯一Java类:

  • MembershipGraphQLListener –注册“ / graphql” Servlet侦听器。
  • MembershipGraphQLApi – GraphQL端点。 仅包装现有的@Stateless服务。
  • MembershipErrorHandler –处理异常。

使用graphQL-spqr的注释, MembershipGraphQLApi类实际上只是描述和包装了现有的@Stateless服务:

@RequestScopedpublic class MembershipGraphQLApi {@Injectprivate MembershipService membershipService;// ...@GraphQLQuery(name = "memberships")public List<Membership> getAllMemberships(Optional<MembershipFilter> filter,@GraphQLArgument(name = "skip") Optional<Integer> skip,@GraphQLArgument(name = "first") Optional<Integer> first) {return membershipService.getAllMemberships(filter, skip, first);   }// ...}

我的希望–我们很快将在Java EE(或Jakarta EE或MicroProfile)中提供一个JAX-QL(或其他东西),以使其变得更加简单!

首先是一些REST

我正在使用MicroProfile OpenAPI和Swagger UI为REST端点创建Open API定义。

您可以使用http:// localhost:8080 / membership / rest / openapi-ui /测试一些查询

示例 –获取所有成员资格:

GET http://localhost:8080/membership/rest

这将返回:

[{"membershipId": 1,"owner": {"id": 1,"names": ["Natus","Phillip"],"surname": "Kruger"},"type": "FULL"},{"membershipId": 2,"owner": {"id": 2,"names": ["Charmaine","Juliet"],"surname": "Kruger"},"type": "FULL"},{"membershipId": 3,"owner": {"id": 3,"names": ["Koos"],"surname": "van der Merwe"},"type": "FULL"},{"membershipId": 4,"owner": {"id": 4,"names": ["Minki"],"surname": "van der Westhuizen"},"type": "FREE"}]

示例 –获得一定的成员资格(1):

GET http://localhost:8080/membership/rest/1

这将返回:

{"membershipId": 1,"owner": {"id": 1,"names": ["Natus","Phillip"],"surname": "Kruger"},"type": "FULL"}

现在让我们看一下GraphQL

该应用程序包括GraphiQL UI(作为Webjar),可以轻松测试某些GraphQL查询

您可以使用http:// localhost:8080 / membership / graph / graphiql /测试一些查询

因此,让我们来看看GraphQL是否兑现了“不再需要过度提取和提取不足”的承诺。

获取所有成员资格和所有字段(与REST相同)

query Memberships {memberships{...fullMembership}}fragment fullMembership on Membership {membershipIdowner{...owner}type}fragment owner on Person {idnamessurname  }

这将返回所有值,但是,现在很容易定义应包括哪些字段…

获取所有会员资格,但仅包括id字段

query Memberships {memberships{...membershipIdentifiers}}fragment membershipIdentifiers on Membership {membershipId}

现在产生的有效负载要小得多:

{"data": {"memberships": [{"membershipId": 1},{"membershipId": 2},{"membershipId": 3},{"membershipId": 4}]}}

现在,仅获取特定类型的会员资格(因此,获取所有免费会员资格)

query FilteredMemberships {memberships(filter:{type:FREE}){...fullMembership}}fragment fullMembership on Membership {membershipIdowner{...owner}type}fragment owner on Person {idnamessurname  }

这将仅返回免费会员资格。 好酷!

甚至更好,所有姓氏的成员都以“ Kru”开头

query FilteredMemberships {memberships(filter:{surnameContains: "Kru"}){...fullMembership}}fragment fullMembership on Membership {membershipIdowner{...owner}type}fragment owner on Person {idnamessurname  }

太好了! 我们找到了两个人:

{"data": {"memberships": [{"membershipId": 1,"owner": {"id": 1,"names": ["Natus","Phillip"],"surname": "Kruger"},"type": "FULL"},{"membershipId": 2,"owner": {"id": 2,"names": ["Charmaine","Juliet"],"surname": "Kruger"},"type": "FULL"}]}}

使用客户端上的变量获取特定成员资格:

query Membership($id:Int!) {membership(membershipId:$id){...fullMembership}}fragment fullMembership on Membership {membershipIdowner{...owner}type}fragment owner on Person {idnamessurname  }

变量:

{"id":1}

在特定条件下包括字段:

query Membership($id:Int!,$withOwner: Boolean!) {membership(membershipId:$id){...fullMembership}}fragment fullMembership on Membership {membershipIdowner @include(if: $withOwner){...owner}type}fragment owner on Person {idnamessurname  }

变量:

{"id":1,"withOwner": false}

这将排除所有者(正确包括):

{"data": {"membership": {"membershipId": 1,"type": "FULL"}}}

分页

让我们使用get all查询,但要分页。

query Memberships($itemsPerPage:Int!,$pageNumber:Int!) {memberships(first:$itemsPerPage,skip:$pageNumber) {membershipIdowner{namessurname}type}}

变量:

{"itemsPerPage": 2,"pageNumber": 1}

这将返回前2个结果,然后您可以通过增加“ pageNumber”值来进行分页。

变异

创造

mutation CreateMember {createMembership(membership: {type:FULL,owner: {names: "James",surname:"Small"}}) {membershipId}}

这将创建新的成员资格并返回ID。

更新资料

mutation EditMember($membership: MembershipInput!) {createMembership(membership:$membership) {membershipId}}

变量:

{"membership": {"membershipId": 2,"owner": {"names": ["Charmaine","Juliet"],"surname": "Krüger"},"type": "FULL"}}

(在克鲁格大学添加了变音符号,现在应该是克鲁格)

删除

mutation DeleteMembership($id:Int!){deleteMembership(membershipId:$id){membershipId}}

变量:

{"id":1}

这将删除成员资格1。

例外。

MembershipErrorHandler转换一个ConstraintViolationException(在bean验证失败时引发),并为GraphQL创建一个不错的错误消息。

因此,让我们尝试创建一个姓氏仅为一个字母的成员。

mutation CreateMember($membership: MembershipInput!) {createMembership(membership:$membership) {membershipId}}

变量:

{"membership": {"owner": {"names": "Christina","surname": "S"},"type": "FULL"}}

这将返回bean验证错误消息:

{"data": {"createMembership": null},"errors": [{"message": "Surname 'S' is too short, minimum 2 characters","path": null,"extensions": null}]}

如果您查看Person POJO:

@NotNull(message = "Surname can not be empty") @Size(min=2, message = "Surname '${validatedValue}' is too short, minimum {min} characters")private String surname;

内省

GraphQL的另一个好处是,它具有可查询的架构和类型系统:

{__schema {queryType {namefields {name}}mutationType{namefields{name}}subscriptionType {namefields{name}}}}

上面将描述此端点上可用的查询和变异。

您还可以描述您的模型:

{__type(name: "Membership") {namekindfields {nameargs {name}}}}

摘要

在此示例中,我们没有删除REST,只是添加了GraphQL作为使用者的替代选项。

到现在为止,应该清楚的是,客户端还有更多的选项可以完全根据需要过滤和查询数据。 所有这些都无需服务器做任何额外的工作。 这样可以在客户端进行快速的产品迭代。

线上的有效负载已得到优化,我们正在节省带宽!

再次,我希望–我们很快将在Java EE(或Jakarta EE或MicroProfile)中提供一个JAX-QL(或其他东西),以使其变得更加简单!

翻译自: https://www.javacodegeeks.com/2018/05/graphql-on-wildfly-swarm.html

graphql

graphql_GraphQL在Wildfly群上相关推荐

  1. GraphQL在Wildfly群上

    " GraphQL是API的查询语言,是用于使用现有数据完成这些查询的运行时. GraphQL为您的API中的数据提供了一个完整且易于理解的描述,使客户能够准确地询问他们所需的内容,仅此而已 ...

  2. Hadoop集群上使用JNI,调用资源文件

    hadoop是基于java的数据计算平台,引入第三方库,例如C语言实现的开发包将会大大增强数据分析的效率和能力. 通常在是用一些工具的时候都要用到一些配置文件.资源文件等.接下来,借一个例子来说明ha ...

  3. 在Kubernetes集群上部署高可用Harbor镜像仓库

    这里主要介绍使用kubectl部署Harbor镜像仓库到Kubernetes集群中. 使用Helm部署,参考: https://my.oschina.net/u/2306127/blog/181969 ...

  4. 在生产集群上运行topology

    2019独角兽企业重金招聘Python工程师标准>>> 在生产集群上运行topology 博客分类: 分布式计算 在生产集群上运行topology跟本地模式差不多.下面是步骤: 1) ...

  5. pythonspark集群模式运行_有关python numpy pandas scipy 等 能在YARN集群上 运行PySpark

    有关这个问题,似乎这个在某些时候,用python写好,且spark没有响应的算法支持, 能否能在YARN集群上 运行PySpark方式, 将python分析程序提交上去? Spark Applicat ...

  6. 从认证到调度,K8s 集群上运行的小程序到底经历了什么?

    作者 | 声东  阿里云售后技术专家 导读:不知道大家有没有意识到一个现实:大部分时候,我们已经不像以前一样,通过命令行,或者可视窗口来使用一个系统了. 前言 现在我们上微博.或者网购,操作的其实不是 ...

  7. 在现有K8S集群上安装部署JenkinsX

    在2018年年初,Jenkins X首次发布,它由Apache Groovy语言的创建者Jame Strachan创建.Jenkins X 是一个高度集成化的 CI/CD 平台,基于 Jenkins ...

  8. 如何在tomcat下应用部署日志_如何在kubernete集群上部署springboot应用

    1.打包springboot镜像 2.在kubernete上发布镜像 3.测试 在之前的文章中,我讲了使用kubeadm从0到1搭建kubernete集群,今天我们来聊一下如何在这套k8s集群上部署s ...

  9. 09_Flink入门案例、word-count程序(java和scala版本)、添加依赖、Flink Streaming和Batch的区别 、在集群上执行程序等

    1.9.Flink入门案例-wordCount 1.9.1.开发工具 1.9.2.编写java版本word-count程序 1.9.2.1.添加Flink Maven依赖 1.9.2.2.编写word ...

最新文章

  1. 鲲鹏服务器拦截系统调用,鲲鹏服务器unicfg工具适配OpenEuler 20.03问题
  2. Java项目代码结构
  3. mysql算法函数_十个实用MySQL函数
  4. java散列法的运用实例,Java HashMap compute() 使用方法及示例
  5. dvd刻录软件_如何在Windows 7中刻录照片和视频DVD(无需额外的软件)
  6. P53:进化了8亿年的抑癌基因
  7. 理解storm的ACKER机制原理
  8. Oracle锁庞大大引见
  9. 线性代数第六版答案(全)
  10. 语音芯片,语音合成芯片,嵌入式语音合成软件的区别
  11. 21王道计算机网络pdf百度云,王道计算机网络第五章.pdf
  12. macos显卡测试软件,GpuTest显卡测试软件 for Mac 64位
  13. visio2019怎么对图片加箭头标注,Visio设置图片作为背景
  14. 数据库查询简单练习(五)
  15. Incorrect string value: ‘\xF0\x9F\x91\x82‘ for column ‘address‘ at row 1
  16. Python:将Word转成HTML
  17. 人工智能几行代码实现换脸
  18. VC中自定义打印调试信息函数,打印调试信息到DebugView上
  19. Scrum板与Kanban如何抉择?敏捷工具:curcwz板与按照esvpvaoq
  20. JavaWeb权限管理

热门文章

  1. 牛客网【每日一题】7月31日题目精讲—兔子的区间密码
  2. Codeforces Round #759 (Div. 2, based on Technocup 2022 Elimination Round 3)
  3. 二分:[BJWC2008]秦腾与教学评估
  4. P2149-[SDOI2009]Elaxia的路线【最短路】
  5. P4427-[BJOI2018]求和【LCA】
  6. USACO2.2【统计,dp,模拟,位运算】
  7. K8S Learning(5)——Pod
  8. SpringBoot maven打包源码发布到仓库配置
  9. Vue.js2.0开发环境搭建(三)
  10. 面象对象设计6大原则之三:里氏替换原则