引言

开局两张图,内容全靠编~

ok,如图所示,我在去年曾经写过一篇文章[《闲侃前后端分离的必要性》](https://www.cnblogs.com/rjzheng/p/9185502.html)。嗯,我知道肯定很多人没看过。所以我做一个总结,其实啰里八嗦了一篇文章,就是想说一下现在的大型互联网项目一般是如下两种架构之一
- 前后端半分离架构
- 前后端分离架构

区别分离和半分离的标志在于Controller层由不由前端控制,Controller在前端手里,前端手里握着组装数据的逻辑,那就是前后端分离!否则就是半分离!

那么,半分离和分离的架构是长下面这样的

ps:中小型公司慎重,不要玩前后端分离架构!前端工作量贼大!

那么用上了前后端分离架构后,后端的API一般会按照Restful风格来设计!ResultFul推荐每个URL能操作具体的资源,而且能准确描述服务器对资源的处理动作,通常服务器对资源支持get/post/put/delete/等,用来实现资源的增删改查。前后端分离的架构下,这些api-url是对接的桥梁,采用ResultFul接口地址含义才更清晰、见名知意。

那么,在实践RestFul风格的API的有一个致命的缺陷,是神马类?嗯,带着你的疑惑开始本文

正文

RestFul的缺陷

假设,此时我们有两个资源分别是BookAuthor,这两个资源对应的ER图如下

相应的API有

POST /books

GET /books/{id}

POST /authors

GET /authors/{id}

我们有一个需求,需要查询id=1的图书信息!

那我们的请求地址是这样的

GET /books/1

返回结果是这样的

[{
"id": 1,
"bookname": Harry Potter,
"price": 56.00,
"author_id": 2
}]

这时候前端MM拿到这个结果后,傻了眼!这里怎么能直接返回author_id呢,难道直接把author_id显示在界面上么?不可能啊,界面上要显示的是author_name才行!

OK,那么在这种情况下,有两种方式可以解决问题!

(1) 跟后端沟通,让他增加一个接口

嗯,我们复习一下什么是VO对象。

VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。

那可以让后端封装一个接口,后端帮你把数据拼装好,提供API如下

GET /bookVOs/1

这样直接返回的结果就是

[{
"id": 1,
"bookname": Harry Potter,
"price": 56.00,
"author_name": J. K. Rowling
}]

当然,因为你这是临时让后端加接口,可能会有如下情形产生

OK,回到正题,这样做的缺点主要有两个

  • 前后端强耦合在一起,前端界面发生变动,后端VO对象跟着一起变
  • 如果BookVO对象在手机端、PC端、APP端的显示内容都不一样,你可能在项目中会有BookPcVO类、BookH5VO类、BookAppVO类,VO类大大膨胀!

(2) 自己做适配

这个也很简单,前端获得结果后,取出author_id: 2这条记录,然后再去调用地址

GET /authors/2

得到结果,然后进行组装显示!

当然,这个时候会有如下情形产生(这就是我注孤生的原因!)

当然,这种做法的缺点也很明显

  • 返回了一堆前端并不需要的数据
  • 徒增前后端的交互次数

ok,通过上面的描述,大家应该能体会到Rest的缺点:REST接口时返回的数据格式、数据类型都是后端预先定义好的,如果返回的数据格式并不是调用者所期望的,调用者在处理上比较麻烦!

那么,有没有办法让前端自定灵活的使用查询语句,自己想捞什么数据就捞什么数据呢?

有的,那就是Graphql!

Graphql的出现

Graphql其实要这样理解

Graphql=grap(图)+query+lanage

是一种基于图的查询语言!那么,这张图长什么样?

OK,首先你要声明一下,你的图结构,嗯,用的就是Graphql的语法啦,像下面这样

type Book {
id: Int
bookname: String
authors: [Author]
}
type Author {
id: Int
name: String
age: String
}
type Query {
getBook(id: Int): Book
}
schema {
query: Query
}

对上面的语句进行一下解释。这里一共声明了三个类BookAuthorQuery!其实,BookAuthor大家都可以猜都出来是指啥,需要注意的一点是authors: [Author]这个地方,用了一个[]的语法,这代表Author是一个数组!

唯一需要说明的是,Query是什么鬼?

Query在这儿表明了该类型是这张图的入口,也就是根节点!我们的查询必须从根节点里的属性开始!这里我为了便于说明,只列了一个属性,也就是getBook,该属性是入口,必须从入口开始查!

那么,生成的图是长下面这样的

这里还有一个Resolver的概念,就是说,GragphQL解析到getBook方法的时候,方法体内容是啥?是在Resovler中定义的,我这里就不贴配置了,感兴趣的可以自己去官网阅读!

OK,接下来就是第二个问题,怎么查?

根据上面我说的,只能从根开始,根是getBook,那语句怎么写呢?如下所示



那你想加个字段,显示作者名字呢?直接像下面这么写

采用这种语法结构,后端的数据模型就变成了一张图,前端可以定制化自己的输出结构,同时可以减少前后端的沟通成本,提高灵活性!

一些疑问

(1)java语言中,对Graphql的支持如何?

在java中,有个jar包为graphql-java-tools提供了对Java的支持。

另外,考虑到现在大多是springboot项目,有大神封装好了starter包,供你们的springboot项目使用!

只需在项目中引入

<!-- graphql -->
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>4.3.0</version>
</dependency>

即可让你的springboot项目拥有graphql的功能,非常方便!

(2)这样做不会加重前后端工作量么?

说句实在话,摸着良心说,前期确实加重了前后端的工作量!

对前端而言:需要去了解Graphql的语法!

对后端而言:不仅需要了解Graphql的语法,还需要去编写SchemaResovler

所以短期内,确实增加了工作量!但是从长远来看,同时降低了前后端的工作量!第一,前端不用了解后端的数据结构,GraphQL自己生成可交互式的接口文档,前端可以自己测试调用

第二,后端不用在编写什么接口文档,GrapQL自动帮你生成,用起来非常舒心!

总结

本文介绍了Rest的缺点,以及Graphql的基本知识,希望大家有所收获!

【原创】从Rest到Graphql的更多相关文章

  1. 记一次通过c#运用GraphQL调用Github api

    阅读目录 GraphQL是什么 .net下如何运用GraphQL 运用GraphQL调用Github api 结语 一.Graphql是什么 最近在折腾使用Github api做个微信小程序练练手,本 ...

  2. 【赠书】300- 59篇原创带你进入 JavaScript 生态圈

    点击上方"前端自习课"关注,学习起来~ 不知不觉,[前端自习课]已经连续推送300天整(不含删除的文章),每天一篇,正如公众号的 Slogan:每日清晨,享受一篇前端优秀文章. 运 ...

  3. GraphQL入门有这一篇就足够了

    GraphQL入门有这一篇就足够了:https://blog.csdn.net/qq_41882147/article/details/82966783 版权声明:本文为博主原创文章,遵循 CC 4. ...

  4. REST,RPC和GraphQL应用场景,WebHooks、WebSocket、HTTP Streaming应用场景。

    一.请求--响应API. 请求--响应类的API的典型做法是,通过基于HTTP的Web服务器暴露一个/套接口.API定义一些端点,客户端发送数据的请求到这些端点,Web服务器处理这些请求,然后返回响应 ...

  5. 【原创分享·支付宝支付】HBuilder打包APP调用支付宝客户端支付

    前言 最近有点空余时间,所以,就研究了一下APP支付.前面很早就搞完APP的微信支付了,但是由于时间上和应用上的情况,支付宝一直没空去研究.然后等我空了的时候,发现支付宝居然升级了支付逻辑,虽然目前还 ...

  6. 【原创分享·微信支付】C# MVC 微信支付教程系列之现金红包

            微信支付教程系列之现金红包           最近最弄这个微信支付的功能,然后扫码.公众号支付,这些都做了,闲着无聊,就看了看微信支付的其他功能,发现还有一个叫“现金红包”的玩意,想 ...

  7. 【原创分享·微信支付】 C# MVC 微信支付教程系列之扫码支付

    微信支付教程系列之扫码支付                  今天,我们来一起探讨一下这个微信扫码支付.何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添 ...

  8. 【原创分享·微信支付】 C# MVC 微信支付教程系列之公众号支付

    微信支付教程系列之公众号支付         今天,我们接着讲微信支付的系列教程,前面,我们讲了这个微信红包和扫码支付.现在,我们讲讲这个公众号支付.公众号支付的应用环境常见的用户通过公众号,然后再通 ...

  9. 【原创分享·微信支付】C# MVC 微信支付之微信模板消息推送

    微信支付之微信模板消息推送                    今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不 ...

随机推荐

  1. 在 ASP.NET Core 中使用 MySql 踩坑记录

    使用 Pomelo.EntityFrameworkCore.MySql 生成 MySQL 数据库 关于如何使用请查看项目文档即可 组件地址:https://github.com/PomeloFound ...

  2. Java8与传统的日期和时间类详解

    一.传统的日期时间类(Date和Calendar) 1. Date类 这里的Date是位于java.util包下的类,而不是java.sql包下的date类,Date对象即包含日期也包含时间,从JDK ...

  3. Scrapy-redis<数据库篇>

    scrapy-redis爬虫数据库连接部分——windows准备做salve,Linux准备做master开展工作 首先处理简单的windows熟悉的环境——安装Redis服务和Redis可视化~可视 ...

  4. Xapian索引-文档检索过程分析之匹配百分比

    本文属于文档检索过程分析的一部分,重点分析文档匹配百分比(percent)的计算过程. 1 percent是什么? 我们之前分析的检索demo: Xapian::Query term_one = Xa ...

  5. C#版[击败99.69%的提交] - Leetcode 242. 有效的同构异形词 - 题解

    C#版 - Leetcode 242. 有效的同构异形词 - 题解 Leetcode 242.Valid Anagram 在线提交: https://leetcode.com/problems/val ...

  6. Promise来控制JavaScript的异步执行

    一般来说,js.html都是按照从上至下这种方式来进行执行的.这就造成了,基本上所有的执行过程都是在一个线程中进行. 我们都知道,ajax的使用大大的提高了前后台的沟通效率,那么有没有什么方式,让js ...

  7. C#枚举的简单使用

    枚举这个名词大家都听过,很多小伙伴也使用过, 那么枚举在开发中能做什么,使用它后能给程序代码带来什么改变,为什么用枚举. 各位看官且坐下,听我一一道来. 为什么使用枚举? 1.枚举能够使代码更加清晰, ...

  8. cocos creator主程入门教程(十)—— A*寻路

    摘要: 五邑隐侠,本名关健昌,10年游戏生涯,现隐居五邑.本系列文章以TypeScript为介绍语言. 这一篇介绍A*寻路算法.在RPG.SLG.模拟经营类游戏,有需要给角色寻路的需求,一般寻路我们采 ...

  9. 利用 Blob 处理 node 层返回的二进制文件流字符串并下载文件

    博客地址:https://ainyi.com/65 解释 | 背景 看到标题有点懵逼,哈哈,实际上是后端将文件处理成二进制流,返回到前端,前端处理这个二进制字符串,输出文件或下载 最近公司有个需求是用 ...

  10. Go channel实现源码分析

    go通道基于go的并发调度实现,本身并不复杂,go并发调度请看我的这篇文章:go并发调度原理学习 1.channel数据结构 type hchan struct { qcount uint // 缓冲 ...