java world_Java World中的GraphQL简介

java world

许多人认为GraphQL仅适用于前端和JavaScript,它在Java等后端技术中不占优势,但事实确实如此。

还经常将GraphQL与REST进行比较,但是这种比较是否合理?

首先,让我开始回答其中最重要的问题。 什么是GraphQL?

如果您查看官方网站,将会看到类似的内容

“ GraphQL是API的查询语言,是用于通过使用为数据定义的类型系统执行查询的服务器端运行时。 GraphQL不受任何特定数据库或存储引擎的束缚,而是由您现有的代码和数据提供支持。”

实际上应该说的是

GraphQL是一个规范,仅此而已。

要记住这一点很重要,因为作为开发人员,我们将使用GraphQL的实现。 一些实现已经或多或少地实现了GraphQL规范。 有许多语言的实现,例如JavaScript,Java,PHP,Go和其他语言。 每天都有不同语言和现有语言的新实现。

如果您来自Java背景并且有很多REST API,那么您首先会感兴趣的是GraphQL与您多年来开发的Traditional REST API有何不同。

让我将其放在一个简单的博客的上下文中,该博客由博客文章,博客文章的作者组成,并且可以在博客文章中添加评论。

从数据库的角度来看,这意味着我们有三个表

让我们假设前端是只读的,并从Traditional REST API获取数据,然后将数据呈现给用户。 如果我们要构建这种传统的REST API,则可能最终会得到如下代码

 @RestController  public class SimpleRestController { @RequestMapping (path= "/authors" ) public List getAllAuthors() { ... } @RequestMapping (path= "/authors/{id}" ) public Author getAuthorById( @PathVariable String id) { ... } @RequestMapping (path= "/posts" ) public List getAllPosts( @RequestParam (value= "author_id" , required = false ) String authId) { ... } @RequestMapping (path= "/comments" ) public List getAllComments( @RequestParam (value= "post_id" , required = false ) String postId) { ... }  } 

因此,在这种情况下,如果我们想显示包含作者信息和评论的帖子,我们首先需要致电

  • /帖子

获取所有帖子,然后找到我们想要的帖子,查看authorId是什么,然后调用

  • / authours / <帖子中的ID>

之后,我们需要致电

  • / comments?post_id = <相关帖子的ID>

获取该帖子的所有评论。

显然,这不是最佳方法。 当然,在这种情况下,我们所有人都会做的就是看好API的用例,并牢记这一点来优化端点和响应。 也许我们会将评论嵌入帖子,作者信息或类似内容中。 或者,由于某种原因,如果我们认为没问题,也许我们不会改变任何事情。 无论如何,我们将决定用户可以呼叫哪些端点,以及他们将获得什么样的响应。

确切地说,这是GraphQL的最大区别。 对于GraphQL,通常只有一个端点,例如

  • / graphql

该端点将获取对您的API的所有请求,并发送回所有响应。

起初听起来有点奇怪。 最简单的方法是拥有完整的示例代码。 我将使用一个这样的示例中的代码片段。 要获取完整的代码,只需点击以下URL :https://github.com/vladimir-dejanovic/simple-springboot-graphql-mongo-conftalk-demo

要记住的重要一点是,在GraphQL中,一切都始于模式。 如果我们转到上面的示例,博客文章,GraphQL模式可能看起来像这样:

 type Author { id: ID! name: String! posts: [Post] }  type Post { id: ID! title: String! body: String createdBy: Author! comments: [Comment]  } type Comment { id: ID! createdBy: Author! belongsTo: Post! text: String }  schema { query: Query  }  type Query { allPosts: [Post] allAuthors: [Author]  } 

我们从定义类型开始,对于我们要为表创建的POJO,类型几乎可以是1到1。 首先,我们输入一个名称,然后输入。 字符' '具有特殊含义,表示该字段是必填字段。 如果字段具有此字符并且不存在响应,则它将是无效响应,并且GraphQL将不会将响应发送回去,但会发送适当的错误。

关于模式要记住的重要一点是,所有请求和响应都将使用模式进行验证。 如果请求未通过架构验证,则服务器将不执行任何工作。 同样,如果响应未通过架构验证,则不会将其发送到客户端。

如果您选中“作者”类型,则将看到它具有“帖子数组”类型的字段帖子。 另外,Post具有类型为Author和comments的createdBy字段,其类型为Comment的Array。 这些字段在POJO的中不存在

 Author.java  public class Author {  private final String id;    private final String name;  .....get/set  }  Post.java  public class Post { private final String id;    private String authorId;    private final String title; private final String body;  ...get/set  } 

类似的是注释类型,我稍后会再讲。 定义类型之后,我们可以进入GraphQL模式的核心

 schema { query: Query  } 

这是我们定义与用户互动的地方。 我们说用户可以使用下面定义的Query类型的查询来读取数据。

 type Query { allPosts: [Post] allAuthors: [Author]  } 

Query是一种特殊类型,因为我们在DB中没有此数据,这实际上是传统思维方式中的端点。

如果您是从GitHub链接下载代码,编译并启动的,则可以转到http:// localhost:8080 / 。 然后,您将看到名为GraphiQL的漂亮用户界面。 您可以使用GraphiQL来玩GraphQL API

为了获得所有带有ID,标题和正文的帖子,只需将其输入GraphiQL

 query { allPosts { id title body }  } 

响应应如下所示

 { "data" : { "allPosts" : [ { "id" : "59f4c12e7718af0b1e001072" , "title" : "Who is Ed Wong" , "body" : "Edward Wong Hau Pepelu .....” }, . . . .  } 

例如,如果我们对身体不感兴趣,我们可以输入这样的内容

 query { allPosts { id title }  } 

这样的回应将是这样

 { "data" : { "allPosts" : [ { "id" : "59f4c12e7718af0b1e001072" , "title" : "Who is Ed Wong" , }, . . . .  } 

如您所见,当涉及到GraphQL时,用户在响应中并不总是获得相同的预定义字段集。 用户可以选择说哪些字段应该发回,哪些不应该发回。

允许这样做的Java代码不是那么大。 首先,我们需要定义扩展SimpleGraphQLServlet的 Servlet。

 public class GraphQLEntryPoint extends SimpleGraphQLServlet {    public GraphQLEntryPoint(PostRepository postRepository, AuthorRepository authRepository, CommentRepository commentRepository) { super (buildSchema(postRepository, authRepository, commentRepository)); } private static GraphQLSchema buildSchema(PostRepository postRepository, AuthorRepository authRepository, CommentRepository commentRepository) { return SchemaParser .newParser() .file( "schema.graphqls" ) .resolvers( new Query(postRepository, authRepository), new PostResolver(authRepository, commentRepository), new AuthorResolver(postRepository), new CommentResolver(authRepository, postRepository)) .build() .makeExecutableSchema(); }  } 

在这里,我创建了一个模式解析器,该解析器打开了我的GraphQL模式文件,之后添加了解析器,然后调用build和makeExecutableSchema方法。

这里的重要部分是解析器。 解析器是GraphQL将用于解决用户请求的类。

首先,最重要的是Query类。 它与模式中的Query类型具有相同的名称并非偶然。 这就是java GraphQL实现如何从架构中知道哪个类对应于查询逻辑的方式。 您可以使用任何喜欢的名称,只要该类具有相同的名称即可,但是,这意味着新人们也需要知道该名称,因此请保持标准,并且对于只读使用Query。

这是类查询的代码

 public class Query implements GraphQLRootResolver { private final PostRepository postRepository; private final AuthorRepository authRepo; public List<Post> allPosts() { return postRepository.findAll(); }    public List<Author> allAuthors() { return authRepo.findAll(); }  } 

它实现了GraphQLRootResolver ,如您所见,对于GraphQL模式中的每一行都有一个方法。

有一个叫allPost方法,该方法返回后的名单,也有方法allAuthors返回作者列表。 为了使我们的API能够正常工作,这就是所有这些。

如果您回到GraphiQL并输入像这样的输入

 query { allPosts { id title createdBy { name } }  } 

响应将是这样的

 { "data" : { "allPosts" : [ { "id" : "59f4c12e7718af0b1e001072" , "title" : "Who is Ed Wong" , "createdBy" : { "name" : "Ed Wong” } }, . . . ]  } 

您将获得所有突然的数据作为响应,这不是Post pojo的一部分。 正如我们所看到的,Query类没有任何作用,它只是返回Post类型的纯pojo列表。 那么,createdBy字段的作者信息来自何处?

为此,我们需要查看另一个解析器PostResolver,以使其更加精确,因此让我们看一下它的代码

 public class PostResolver implements GraphQLResolver<Post> {    private final AuthorRepository authRepository; private final CommentRepository commentRepository;    public Author createdBy(Post post) { return authRepository.findOne(post.getAuthorId()); }    public List<Comment> comments(Post post) { return commentRepository.findByPostId(post.getId()); }  } 

PostResolver实现了GraphQLResolver ,我们不得不说是哪种类型,在这种情况下,它是Post的类型 。 如您所见,Post中存在模式中的所有字段,而Pojo Post中不存在。 有一个createdBy方法,该方法采用Post类型的参数并返回Author。

此外,还有方法注释 ,该方法注释也采用Post类型的参数并返回Comment列表。

这就是全部,这就是我在代码中使用的GraphQL的java实现如何知道如何解析pojo中不存在的字段的方式。 在pojo的情况下,这非常简单,如果用户请求该字段,则只需调用适当的get方法,对于其他字段,必须为实现GraphQLResolver的类型提供解析器,并且需要一种具有正确签名和返回类型的方法。

如您所见,与我们一直以来创建的传统REST API相比,使用GraphQL,用户可以更好地控制他/她将获取哪些数据以及采用哪种格式。 因此,从用户的角度来看,这当然具有更好的用户体验,因为它具有更大的灵活性。 但是,这也意味着后端需要完成更多工作,因此系统在高负载下仍然可以正常运行。

在传统的REST API中,我们作为开发人员,在用户与我们的端点进行交互的方式,他们将获得什么样的响应以及用户请求将遵循的路径的完全控制之下,将在我们的代码中进行控制。 如我们所见,使用GraphQL不再是这种情况。 我们知道的是,用户将点击解析器,而不是如何或通过哪个路径。 因此,优化困难得多。

幸运的是,并不是所有的东西都丢失了,我们仍然可以使用许多旧的技巧来解决这些新的/旧的问题。 例如,如果采用传统的REST API,解决高性能问题的一种方法是拥有一个带有端点的控制器,调用服务,然后该服务将承担繁重的工作。 在此设置中,我们可以缓存所有对服务的调用,并以这种简单的方式获得良好的性能。 我们可以使用GraphQL做类似的事情,唯一的不同是控制器将调用服务,而不是控制器调用服务。

使用GraphQL可能会遇到一些棘手的问题,但是,可以结合使用一些过去的技巧来使用过去的许多技术。 当然,每天都会出现许多解决问题的新方法。

我只在这里向您展示了如何读取数据,您当然也可以创建/编辑/修改数据,并使用GraphQL进行更多操作。 当您涉及GraphQL在构建API中提供的功能时,我与您分享的内容只是从头开始。

您需要记住的重要一点是,尽管GraphQL相对较新,但没有它也可以实现它提供的所有功能。 但是,在这种情况下,您将需要考虑允许用户做什么以及他们如何将请求发送到您的API。 对于GraphQL,其他人已经考虑过了,而您所要做的就是实现它。

最后,GraphQL API是REST API,这是高级REST API,具有许多功能和特性,因此更加精确。 这就是为什么问自己的问题,这是一件好事,您是否真的需要GraphQL提供的功能,并且会为您的API和为此API构建域的域增加更多的问题或解决方案。 也许GraphQL正是您所需要的,但也许又是旧的传统REST API所需要的。

资源资源

  • 代码示例https://github.com/vladimir-dejanovic/simple-springboot-graphql-mongo-conftalk-demo
  • GraphQL Java实现https://github.com/graphql-java/graphql-java
  • 弗拉基米尔·德亚诺维奇(Vladimir Dejanovic)在摩洛哥Devoxx上谈论GraphQL与传统REST API的关系https://www.youtube.com/watch?v=2FH93GaoIto

翻译自: https://www.javacodegeeks.com/2017/12/gentle-intro-graphql-java-world.html

java world

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/334285.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

快速排序 动图_Java十大排序算法最强总结

看到一篇很不错的文章&#xff0c;不多说&#xff0c;看吧排序算法说明0.1 排序的定义对一序列对象根据某个关键字进行排序。0.2 术语说明稳定&#xff1a;如果a原本在b前面&#xff0c;而ab&#xff0c;排序之后a仍然在b的前面&#xff1b;不稳定&#xff1a;如果a原本在b的前…

feignclient注解使用_从 Feign 使用注意点到 RESTFUL 接口设计规范

最近项目中大量使用了Spring Cloud Feign来对接http接口&#xff0c;踩了不少坑&#xff0c;也产生了一些对RESTFUL接口设计的想法&#xff0c;特此一篇记录下。SpringMVC的请求参数绑定机制了解Feign历史的朋友会知道&#xff0c;Feign本身是Netflix的产品&#xff0c;Spring …

python写接口测试代码_python写运单接口测试(增改查)完整代码

importrequestsimportjsonfrom urllib importparseclassHttpWayBillRquest:运单的增改查 defaccess_token(self):获取tokenurl http://xxxxxxxxx.comusername 12333password 12334566res_json requests.get(url, auth(username, password)).json()print(access_token的结果为&a…

linux vim自动执行快捷键,Linux Vim快捷键操作命令整理

VIM中常用的替换模式总结1&#xff0c;简单替换表达式替换命令可以在全文中用一个单词替换另一个单词&#xff1a;:%s/four/4/g“%” 范围前缀表示在所有行中执行替换。最后的 “g” 标记表示替换行中的所有匹配点。如果仅仅对当前行进行操作&#xff0c;那么只要去掉%即可如果…

eclipse占用内存过大_Java性能调优学习(三)-jmap+mat分析内存溢出问题实战

上一节我们讲了jinfo&#xff0c;jstat&#xff0c;jmap的使用&#xff0c;还简单的讲了下如何使用jmap导出内存映像文件&#xff0c;这次&#xff0c;我们来实战一把内存溢出问题。环境准备首先我们先模拟一下内存溢出的场景&#xff0c;以下这段代码在访问后肯定会造成堆内存…

spring boot自测_将测微仪与Spring Boot 2一起使用

spring boot自测这是快速入门&#xff0c;介绍了如何使用出色的Micrometer库来检测基于Spring Boot 2的应用程序并在Prometheus中记录指标 介绍 Micrometer在不同监视工具提供的客户端库上提供了基于Java的外观。 以Prometheus为例&#xff0c;如果我要将Java应用程序与Prome…

微软和 Windows 的发展简史

20世纪60年代中期&#xff0c;美国达特茅斯学院院长、匈牙利人约翰凯梅尼&#xff08;J. Kemeny&#xff09;和数学系教授托马斯卡茨&#xff08;Thomas E. Kurtz&#xff09;认为&#xff0c;像FORTRAN&#xff08;世界上最早出现的计算机高级程序设计语言&#xff09;那样的语…

elaseticsearch 配置ik分词器的热更新_Elasticsearch从入门到放弃:分词器初印象

Elasticsearch 系列回来了&#xff0c;先给因为这个系列关注我的同学说声抱歉&#xff0c;拖了这么久才回来&#xff0c;这个系列虽然叫「Elasticsearch 从入门到放弃」&#xff0c;但只有三篇就放弃还是有点过分的&#xff0c;所以还是回来继续更新。之前我们聊过了 Elasticse…

服务器windows模拟linux环境,科学网—Windows不用虚拟机或双系统,轻松实现shell环境:gitforwindows - 刘永鑫的博文...

windows缺少shell命令支持用过Linux服务器分析数据的小伙伴&#xff0c;一定对Linux强大Shell命令所折服&#xff0c;经常会感觉windows缺少这些命令而感觉不方便。还有想学习Linux Shell命令的小伙伴&#xff0c;一直没有一个很好的学习环境。双系统安装涉及分区改变对硬盘数据…

Mac OS 系统的发展历史

文章目录System 1.0&#xff08;1984&#xff09;System 2.0&#xff08;1985&#xff09;System 3.0&#xff08;1986&#xff09;System 4.0&#xff08;1987&#xff09;System 5.0&#xff08;1987&#xff09;System 6.0 &#xff08;1988&#xff09;System 7 (1991 )Sys…

苹果公司的电脑发展史——硬件篇

文章目录一、Apple I&#xff08;1976&#xff09;二、Apple II&#xff08;1977&#xff09;三、Lisa&#xff08;1983&#xff09;四、Macintosh&#xff08;1984&#xff09;五、PowerBook&#xff08;1991&#xff09;六、iMac&#xff08;1998&#xff09;七、iBook&#…

my.ini修改后服务无法启动_Spring Cloud Eureka 服务实现不停机(Zero-downtime)部署

问题互联网产品高速迭代&#xff0c;通常伴随着高频次的版本发布。部署新版上线需要重启服务&#xff0c;直接 kill 服务进程可能会造成服务短暂不可用&#xff0c;从而影响到正在使用的用户。Spring Cloud 项目中一般会用到 Ribbon 作为负载均衡&#xff0c;那么是不是只要保证…

苹果电脑 Mac OS X 系统诞生的故事和发展历史

文章目录CoplandNeXTRhapsodyOS XPublic Beta (Kodiak)Mac OS X v10.0 (Cheetah)Mac OS X v10.1 (Puma)Mac OS X v10.2 (Jaguar)Mac OS X v10.3 (Panther)Mac OS X v10.4 (Tiger)Mac OS X v10.5 (Leopard)Mac OS X v10.6 (Snow Leopard)Mac OS X Lion2001 年 3 月 24 日&#x…

Mac OS 的历史

文章目录概述1980年代前20世纪80年代20世纪90年代2000年以后概述 纵观电脑之历史&#xff0c;操作系统与计算机硬件的发展息息相关。 操作系统之本意原为提供简单的工作排序能力&#xff0c;后为辅助更新更复杂的硬件设施而渐渐演化。 从最早的批处理模式开始&#xff0c;分…

java 反射 速度_Java反射,但速度更快

java 反射 速度在编译时不知道Java类的最快方法是什么&#xff1f; Java框架通常会这样做。 很多。 它可以直接影响其性能。 因此&#xff0c;让我们对不同的方法进行基准测试&#xff0c;例如反射&#xff0c;方法句柄和代码生成。 用例 假设我们有一个简单的Person类&#x…

macOS 内核之 OS X 系统的起源

文章目录一、苹果公司早期(1972-1991)二、苹果在操作系统上的尝试(1991-1997)2.1 Star Trek 项目 (1992-1993)2.2 Copland-Mac OS 8 (1994-1996)三、收购与转折(1996-1997)四、NeXT 篇章4.1 NEXTSTEP(1985-1997)4.2 OpenStep(1993-1997)五、Mach 的历史5.1 Rochester’s Intell…

docker create_Docker动手教程2.2:容器基本操作2

内容摘要暂停/取消暂停容器删除容器进入容器创建容器暂停/取消暂停容器暂停容器命令&#xff1a;docker pause 容器ID/容器名注意STATUS列&#xff0c;被暂停的容器的状态依旧是“Up”&#xff0c;但是后面括号显示为“Paused”。取消暂停命令&#xff1a;docker unpause 容器I…

关于 Mac OS X 内核技术来源

Mach&#xff08;Multiple Asynchronously Communication Hosts&#xff09; 是一个由卡内基梅隆大学开发的操作系统内核&#xff0c;Mach的开发是为了取代BSD的UNIX核心。 Mach 内核的设计目标之一是要兼容 Unix 系统。 当初他们的设想是&#xff0c;真正的操作系统可以作为一…

用C语言编程画出图形,C语言图形编程(六) -图形程序设计实例:零件图形的绘制...

实例&#xff1a;一个零件图形的绘制有一个零件图&#xff0c;如下&#xff1a;对图3-1中的零件图形&#xff0c;如何根据它所标注的尺寸&#xff0c;按照适当的顺序有步聚地画出该图形&#xff0c;这首先要分析此零件图形的几何关系&#xff0c;了解构成这个图形各线段的性质&…

mfc怎么获取进程的线程数_Python多线程获取小米应用商店App,看看我是怎么做到的

一、【项目背景】小米应用商店给用户发现最好的安卓应用和游戏,安全可靠&#xff0c;可是要下载东西要一个一个的搜索太麻烦了。而且速度并不是很快。今天小编就教大家利用多线程爬取小米应用商店的游戏模块&#xff0c;快速获取我们想要的软件安装包。二、【项目目标】目标 &a…