<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          為什么我勸你放棄了Restful API?

          共 6895字,需瀏覽 14分鐘

           ·

          2021-12-11 09:09

          1、年后準(zhǔn)備跳槽可以看看

          2、公司規(guī)定所有接口都用 POST請求,這是為什么?

          3、為什么阿里強(qiáng)制 boolean 類型變量不能使用 is 開頭?

          4、MyBatis批量插入幾千條數(shù)據(jù),請慎用foreach

          5、有了 for (;;) ,為什么還需要while (true) ?到底哪個(gè)更快?

          來自:IT研究僧大師兄?| 責(zé)編:樂樂

          鏈接:toutiao.com/i6833818331884028419


          背景

          REST作為一種現(xiàn)代網(wǎng)絡(luò)應(yīng)用非常流行的軟件架構(gòu)風(fēng)格,自從Roy Fielding博士在2000年他的博士論文中提出來到現(xiàn)在已經(jīng)有了20年的歷史。它的簡單易用性,可擴(kuò)展性,伸縮性受到廣大Web開發(fā)者的喜愛。
          REST 的 API 配合JSON格式的數(shù)據(jù)交換,使得前后端分離、數(shù)據(jù)交互變得非常容易,而且也已經(jīng)成為了目前Web領(lǐng)域最受歡迎的軟件架構(gòu)設(shè)計(jì)模式。

          但隨著REST API的流行和發(fā)展,它的缺點(diǎn)也暴露了出來:
          • 濫用REST接口,導(dǎo)致大量相似度很高(具有重復(fù)性)的API越來越冗余。

          • 對于前端而言:REST API粒度較粗,難以一次性符合前端的數(shù)據(jù)要求,前端需要分多次請求接口數(shù)據(jù)。增加了前端人員的工作量。

          • 對于后端而言:前端需要的數(shù)據(jù)往往在不同的地方具有相似性,但卻又不同,比如針對同樣的用戶信息,有的地方只需要用戶簡要信息(比如頭像、昵稱),有些地方需要詳細(xì)的信息,這就需要開發(fā)不同的接口來滿足這些需求。當(dāng)這樣的相似但又不同的地方多的時(shí)候,就需要開發(fā)更多的接口來滿足前端的需要。增加了后端開發(fā)人員的工作量和重復(fù)度。

          那我們來分析一下,當(dāng)前端需求變化,涉及到改動(dòng)舊需求時(shí),會(huì)有以下這些情況:
          做加法:
          產(chǎn)品需求增加,頁面需要增加功能,數(shù)據(jù)也就相應(yīng)的要增加顯示,那么REST接口也需要做增加,這種無可厚非。
          做減法:
          產(chǎn)品需求減少,頁面需要減少功能,或者減少某些信息顯示,那么數(shù)據(jù)就要做減法。
          一種通常懶惰的做法是,前端不與后端溝通,僅在前端對數(shù)據(jù)選擇性顯示。
          因?yàn)楹蠖私涌谀軌驖M足數(shù)據(jù)需要,僅僅是在做顯示的時(shí)候?qū)?shù)據(jù)進(jìn)行了選擇性顯示,但接口的數(shù)據(jù)是存在冗余的,這種情況一個(gè)是存在數(shù)據(jù)泄露風(fēng)險(xiǎn),另外就是數(shù)據(jù)量過大時(shí)造成網(wǎng)絡(luò)流量過大,頁面加載緩慢,用戶流量費(fèi)白白消耗,用戶體驗(yàn)就會(huì)下降。
          另外一種做法就是告知后端,要么開發(fā)新的接口,要么,修改舊接口,刪掉冗余字段。
          但一般來說,開發(fā)新接口往往是后端開發(fā)人員會(huì)選擇的方案,因?yàn)檫@個(gè)方案對現(xiàn)有系統(tǒng)的影響最低,不會(huì)有額外的風(fēng)險(xiǎn)。
          修改舊接口刪除冗余數(shù)據(jù)的方案往往開發(fā)人員不會(huì)選擇,這是為什么呢?
          這就涉及到了系統(tǒng)的穩(wěn)定性問題了,舊接口往往不止是一個(gè)地方在用,很有可能很多頁面、設(shè)置不同客戶端、不同服務(wù)都調(diào)用了這個(gè)接口獲取數(shù)據(jù),不做詳細(xì)的調(diào)查,是不可能知道到底舊接口被調(diào)用了多少次,一旦改動(dòng)舊接口,涉及范圍可能非常大,往往會(huì)引起其他地方出現(xiàn)崩潰。改動(dòng)舊接口成本太高,所以往往不會(huì)被采取。
          同時(shí)做加減法:
          既有加法,又有減法,其實(shí)這種就跟新需求沒啥區(qū)別,前端需要重做頁面,后端需要新寫接口滿足前端需要,但是舊接口還是不能輕舉妄動(dòng)(除非確定只有這一處調(diào)用才可以刪除)。
          往往這個(gè)時(shí)候,其實(shí)用到的數(shù)據(jù)大多都是來自于同一個(gè)DO或者DTO,不過是在REST接口組裝數(shù)據(jù)時(shí),用不同的VO來封裝不同字段,或者,使用同樣的VO,組裝數(shù)據(jù)時(shí)做刪減。
          看到這些問題是不是覺得令人頭大?

          所以需求頻繁改動(dòng)是萬惡之源,當(dāng)產(chǎn)品小哥哥改動(dòng)需求時(shí),程序員小哥哥可能正提著鐵鍬趕來……
          那么有沒有一種方案或者框架,可以使得在用到同一個(gè)領(lǐng)域模型(DO或者DTO)的數(shù)據(jù)時(shí),前端對于這個(gè)模型的數(shù)據(jù)字段需求的改動(dòng),后端可以根據(jù)前端的改動(dòng)和需要,自動(dòng)適配,自動(dòng)組裝需要的字段,返回給前端呢?如果能這樣做的話,那么后端程序猿小哥可能要開心死了,前端妹子也不用那么苦口婆心地勸說后端小哥哥了。
          所以GraphQL隆重出世了!

          GraphQL簡介

          • GraphQL是一種新的API標(biāo)準(zhǔn),它提供了一種比REST更有效、更強(qiáng)大和更靈活的替代方案。

          • 它是由Facebook開發(fā)并開源的,現(xiàn)在由來自世界各地的公司和個(gè)人組成的大型社區(qū)維護(hù)。

          • GraphQL本質(zhì)上是一種基于api的查詢語言,現(xiàn)在大多數(shù)應(yīng)用程序都需要從服務(wù)器中獲取數(shù)據(jù),這些數(shù)據(jù)存儲(chǔ)可能存儲(chǔ)在數(shù)據(jù)庫中,API的職責(zé)是提供與應(yīng)用程序需求相匹配的存儲(chǔ)數(shù)據(jù)的接口。

          • 它是數(shù)據(jù)庫無關(guān)的,而且可以在使用API的任何環(huán)境中有效使用,我們可以理解為GraphQL是基于API之上的一層封裝,目的是為了更好,更靈活的適用于業(yè)務(wù)的需求變化。

          簡單的來說,它:
          它的工作模式是這樣子的:


          GraphQL 對比 REST API 有什么好處?

          REST API 的接口靈活性差、接口操作流程繁瑣,GraphQL 的聲明式數(shù)據(jù)獲取,使得接口數(shù)據(jù)精確返回,數(shù)據(jù)查詢流程簡潔,照顧了客戶端的靈活性。
          客戶端拓展功能時(shí)要不斷編寫新接口(依賴于服務(wù)端),GraphQL 中一個(gè)服務(wù)僅暴露一個(gè) GraphQL 層,消除了服務(wù)器對數(shù)據(jù)格式的硬性規(guī)定,客戶端按需請求數(shù)據(jù),可進(jìn)行單獨(dú)維護(hù)和改進(jìn)。
          REST API 基于HTTP協(xié)議,不能靈活選擇網(wǎng)絡(luò)協(xié)議,而傳輸層無關(guān)、數(shù)據(jù)庫技術(shù)無關(guān)使得 GraphQL 有更加靈活的技術(shù)棧選擇,能夠?qū)崿F(xiàn)在網(wǎng)絡(luò)協(xié)議層面優(yōu)化應(yīng)用。
          舉個(gè)經(jīng)典的例子:前端向后端請求一個(gè)book對象的數(shù)據(jù)及其作者信息。
          我用動(dòng)圖來分別演示下REST和GraphQL是怎么樣的一個(gè)過程。
          先看REST API的做法:
          再來看GraphQL是怎么做的:
          可以看出其中的區(qū)別:
          • 與REST多個(gè)endpoint不同,每一個(gè)的 GraphQL 服務(wù)其實(shí)對外只提供了一個(gè)用于調(diào)用內(nèi)部接口的端點(diǎn),所有的請求都訪問這個(gè)暴露出來的唯一端點(diǎn)。

          • GraphQL 實(shí)際上將多個(gè) HTTP 請求聚合成了一個(gè)請求,將多個(gè) restful 請求的資源變成了一個(gè)從根資源 POST 訪問其他資源的 Comment 和 Author 的圖,多個(gè)請求變成了一個(gè)請求的不同字段,從原有的分散式請求變成了集中式的請求,因此GraphQL又可以被看成是圖數(shù)據(jù)庫的形式。

          那我們已經(jīng)能看到GraphQL的先進(jìn)性,接下來看看它是怎么做的。

          GraphQL 思考模式

          使用GraphQL接口設(shè)計(jì)獲取數(shù)據(jù)需要三步:
          1. 首先要設(shè)計(jì)數(shù)據(jù)模型,用來描述數(shù)據(jù)對象,它的作用可以看做是VO,用于告知GraphQL如何來描述定義的數(shù)據(jù),為下一步查詢返回做準(zhǔn)備;

          2. 前端使用模式查詢語言(Schema)來描述需要請求的數(shù)據(jù)對象類型和具體需要的字段(稱之為聲明式數(shù)據(jù)獲取);

          3. 后端GraphQL通過前端傳過來的請求,根據(jù)需要,自動(dòng)組裝數(shù)據(jù)字段,返回給前端。

          GraphQL的這種思考模式是不是完美解決了之前遇到的問題呢?!
          總結(jié)它的好處:
          在它的設(shè)計(jì)思想中,GraphQL 以圖的形式將整個(gè) Web 服務(wù)中的資源展示出來,客戶端可以按照其需求自行調(diào)用,類似添加字段的需求其實(shí)就不再需要后端多次修改了。
          創(chuàng)建GraphQL服務(wù)器的最終目標(biāo)是:
          允許查詢通過圖和節(jié)點(diǎn)的形式去獲取數(shù)據(jù)。


          GraphQL執(zhí)行邏輯

          有人會(huì)問:
          • 使用了GraphQL就要完全拋棄REST了嗎?

          • GraphQL需要直接對接數(shù)據(jù)庫嗎?

          • 用GraphQL需要對現(xiàn)有的后端服務(wù)進(jìn)行大刀闊斧的修改嗎?

          答案是:NO!不需要!
          它完全可以以一種不侵入的方式來部署,將它作為前后端的中間服務(wù),也就是,現(xiàn)在開始逐漸流行的 前端 —— 中端 —— 后端 的三層結(jié)構(gòu)模式來部署!
          那就來看一下這樣的部署模式圖:
          也就是說,完全可以搭建一個(gè)GraphQL服務(wù)器,專門來處理前端請求,并處理后端服務(wù)獲取的數(shù)據(jù),重新進(jìn)行組裝、篩選、過濾,將完美符合前端需要的數(shù)據(jù)返回。
          新的開發(fā)需求可以直接就使用GraphQL服務(wù)來獲取數(shù)據(jù)了,以前已經(jīng)上線的功能無需改動(dòng),還是使用原有請求調(diào)用REST接口的方式,最低程度的降低更換GraphQL帶來的技術(shù)成本問題!
          如果沒有那么多成本來支撐改造,那么就不需要改造!
          只有當(dāng)原有需求發(fā)生變化,需要對原功能進(jìn)行修改時(shí),就可以換成GraphQL了。

          GraphQL應(yīng)用的基本架構(gòu)

          下圖是一個(gè) GraphQL 應(yīng)用的基本架構(gòu),其中客戶端只和 GraphQL 層進(jìn)行 API 交互,而 GraphQL 層再往后接入各種數(shù)據(jù)源。這樣一來,只要是數(shù)據(jù)源有的數(shù)據(jù), GraphQL 層都可以讓客戶端按需獲取,不必專門再去定接口了。
          一個(gè)GraphQL服務(wù)僅暴露一個(gè) GraphQL Endpoint,可以按照業(yè)務(wù)來進(jìn)行區(qū)分,部署多個(gè)GraphQL服務(wù),分管不同的業(yè)務(wù)數(shù)據(jù),這樣就可以避免單服務(wù)器壓力過大的問題了。

          GraphQL特點(diǎn)總結(jié)

          • 聲明式數(shù)據(jù)獲取(可以對API進(jìn)行查詢): 聲明式的數(shù)據(jù)查詢帶來了接口的精確返回,服務(wù)器會(huì)按數(shù)據(jù)查詢的格式返回同樣結(jié)構(gòu)的 JSON 數(shù)據(jù)、真正照顧了客戶端的靈活性。

          • 一個(gè)微服務(wù)僅暴露一個(gè) GraphQL 層:一個(gè)微服務(wù)只需暴露一個(gè)GraphQL endpoint,客戶端請求相應(yīng)數(shù)據(jù)只通過該端點(diǎn)按需獲取,不需要再額外定義其他接口。

          • 傳輸層無關(guān)、數(shù)據(jù)庫技術(shù)無關(guān):帶來了更靈活的技術(shù)棧選擇,比如我們可以選擇對移動(dòng)設(shè)備友好的協(xié)議,將網(wǎng)絡(luò)傳輸數(shù)據(jù)量最小化,實(shí)現(xiàn)在網(wǎng)絡(luò)協(xié)議層面優(yōu)化應(yīng)用。


          GraphQL支持的數(shù)據(jù)操作

          GraphQL對數(shù)據(jù)支持的操作有:
          • 查詢(Query):獲取數(shù)據(jù)的基本查詢。

          • 變更(Mutation):支持對數(shù)據(jù)的增刪改等操作。

          • 訂閱(Subscription):用于監(jiān)聽數(shù)據(jù)變動(dòng)、并靠websocket等協(xié)議推送變動(dòng)的消息給對方。

          GraphQL的核心概念:圖表模式(Schema)

          要想要設(shè)計(jì)GraphQL的數(shù)據(jù)模型,用來描述你的業(yè)務(wù)數(shù)據(jù),那么就必須要有一套Schema語法來做支撐。
          想要描述數(shù)據(jù),就必須離不開數(shù)據(jù)類型的定義。所以GraphQL設(shè)計(jì)了一套Schema模式(可以理解為語法),其中最重要的就是數(shù)據(jù)類型的定義和支持。
          那么類型(Type)就是模式(Schema)最核心的東西了。
          什么是類型?
          • 對于數(shù)據(jù)模型的抽象是通過類型(Type)來描述的,每一個(gè)類型有若干字段(Field)組成,每個(gè)字段又分別指向某個(gè)類型(Type)。這很像Java、C#中的類(Class)。

          • GraphQL的Type簡單可以分為兩種,一種叫做Scalar Type(標(biāo)量類型),另一種叫做Object Type(對象類型)。

          那么就分別來介紹下兩種類型。

          標(biāo)量類型(Scalar Type)

          標(biāo)量是GraphQL類型系統(tǒng)中最小的顆粒。類似于Java、C#中的基本類型。
          其中內(nèi)建標(biāo)量主要有:
          • String

          • Int

          • Float

          • Boolean

          • Enum

          • ID

          上面的類型僅僅是GraphQL默認(rèn)內(nèi)置的類型,當(dāng)然,為了保證最大的靈活性,GraphQL還可以很靈活的自行創(chuàng)建標(biāo)量類型。

          對象類型(Object Type)

          僅有標(biāo)量類型是不能滿足復(fù)雜抽象數(shù)據(jù)模型的需要,這時(shí)候我們可以使用對象類型。
          通過對象模型來構(gòu)建GraphQL中關(guān)于一個(gè)數(shù)據(jù)模型的形狀,同時(shí)還可以聲明各個(gè)模型之間的內(nèi)在關(guān)聯(lián)(一對多、一對一或多對多)。
          對象類型的定義可以參考下圖:
          是不是很方便呢?我們可以像設(shè)計(jì)類圖一樣來設(shè)計(jì)GraphQL的對象模型。

          類型修飾符(Type Modifier)

          那么,類型系統(tǒng)僅僅只有類型定義是不夠的,我們還需要對類型進(jìn)行更廣泛性的描述。
          類型修飾符就是用來修飾類型,以達(dá)到額外的數(shù)據(jù)類型要求控制。
          比如:
          • 列表:[Type]

          • 非空:Type!

          • 列表非空:[Type]!

          • 非空列表,列表內(nèi)容類型非空:[Type!]!

          在描述數(shù)據(jù)模型(模式Schema)時(shí),就可以對字段施加限制條件。
          例如定義了一個(gè)名為User的對象類型,并對其字段進(jìn)行定義和施加限制條件:
          那么,返回?cái)?shù)據(jù)時(shí),像下面這種情況就是不允許的:
          Graphql會(huì)根據(jù)Schema Type來自動(dòng)返回正確的數(shù)據(jù):

          其他類型

          除了上面的,Graphql還有一些其他類型來更好的引入面向?qū)ο蟮脑O(shè)計(jì)思想:
          • 接口類型(Interfaces):其他對象類型實(shí)現(xiàn)接口必須包含接口所有的字段,并具有相同的類型修飾符,才算實(shí)現(xiàn)接口。

          比如定義了一個(gè)接口類型:
          那么就可以實(shí)現(xiàn)該接口:
          • 聯(lián)合類型(Union Types):聯(lián)合類型和接口十分相似,但是它并不指定類型之間的任何共同字段。幾個(gè)對象類型共用一個(gè)聯(lián)合類型。

          • 輸入類型(Input Types):更新數(shù)據(jù)時(shí)有用,與常規(guī)對象只有關(guān)鍵字修飾不一樣,常規(guī)對象時(shí) type 修飾,輸入類型是 input 修飾。

          比如定義了一個(gè)輸入類型:
          前端發(fā)送變更請求時(shí)就可以使用(通過參數(shù)來指定輸入的類型):
          所以,這樣面向?qū)ο蟮脑O(shè)計(jì)方式,真的對后端開發(fā)人員特別友好!而且前端MVVM框架流行以來,面向?qū)ο蟮脑O(shè)計(jì)思想也越來越流行,前端使用Graphql也會(huì)得心應(yīng)手。

          Graphql 技術(shù)接入架構(gòu)

          那么,該怎么設(shè)計(jì)來接入我們現(xiàn)有的系統(tǒng)中呢?
          • 將Graphql服務(wù)直連數(shù)據(jù)庫的方式:最簡潔的配置,直接操作數(shù)據(jù)庫能減少中間環(huán)節(jié)的性能消耗。

          直連數(shù)據(jù)庫的接入
          • 集成現(xiàn)有服務(wù)的GraphQL層:這種配置適合于舊服務(wù)的改造,尤其是在涉及第三方服務(wù)時(shí)、依然可以通過原有接口進(jìn)行交互。

          集成現(xiàn)有服務(wù)的GraphQL層
          • 直連數(shù)據(jù)庫和集成服務(wù)的混合模式:前兩種方式的混合。

          混合接入方式
          可以說是非常靈活了!你都不用擔(dān)心會(huì)給你帶來任何的麻煩。

          服務(wù)端實(shí)現(xiàn)

          在服務(wù)端, GraphQL 服務(wù)器可用任何可構(gòu)建 Web 服務(wù)器的語言實(shí)現(xiàn)。有以下語言的實(shí)現(xiàn)供參考:
          • C# / .NET

          • Clojure

          • Elixir

          • Erlang

          • Go

          • Groovy

          • Java

          • JavaScript

          • Julia

          • Kotlin

          • Perl

          • PHP

          • Python

          • R

          • Ruby

          • Rust

          • Scala

          • Swift

          種類繁多,幾乎流行的語言都有支持。

          客戶端實(shí)現(xiàn)

          在客戶端,Graphql Client目前有下面的語言支持:
          • C# / .NET

          • Clojurescript

          • Elm

          • Flutter

          • Go

          • Java / Android

          • JavaScript

          • Julia

          • Swift / Objective-C iOS

          • Python

          • R

          覆蓋了眾多客戶端設(shè)計(jì)語言,而其他語言的支持也在推進(jìn)中。

          Graphql的一些服務(wù)

          整理了下目前比較流行的服務(wù)框架:
          • Apollo Engine:一個(gè)用于監(jiān)視 GraphQL 后端的性能和使用的服務(wù)。
            Graphcool (github): 一個(gè) BaaS(后端即服務(wù)),它為你的應(yīng)用程序提供了一個(gè) GraphQL 后端,且具有用于管理數(shù)據(jù)庫和存儲(chǔ)數(shù)據(jù)的強(qiáng)大的 web ui。

          • Tipe (github): 一個(gè) SaaS(軟件即服務(wù))內(nèi)容管理系統(tǒng),允許你使用強(qiáng)大的編輯工具創(chuàng)建你 的內(nèi)容,并通過 GraphQL 或 REST API 從任何地方訪問它。

          • AWS AppSync:完全托管的 GraphQL 服務(wù),包含實(shí)時(shí)訂閱、離線編程和同步、企業(yè)級(jí)安全特性以及細(xì)粒度的授權(quán)控制。

          • Hasura:一個(gè) BaaS(后端即服務(wù)),允許你在 Postgres 上創(chuàng)建數(shù)據(jù)表、定義權(quán)限并使用 GraphQL 接口查詢和操作。

          Graphql的一些工具:
          • graphiql (npm): 一個(gè)交互式的運(yùn)行于瀏覽器中的 GraphQL IDE。

          • Graphql Language Service: 一個(gè)用于構(gòu)建 IDE 的 GraphQL 語言服務(wù)(診斷、自動(dòng)完成等) 的接口。

          • quicktype (github): 在 TypeScript、Swift、golang、C#、C++ 等語言中為 GraphQL 查 詢生成類型。

          想要獲取更多關(guān)于Graphql的一些框架、工具,可以去awesome-graphql:一個(gè)神奇的社區(qū),維護(hù)一系列庫、資源等,地址是
          https://github.com/chentsulin/awesome-graphql。
          想要學(xué)習(xí)更多Graphql的知識(shí),可以去GraphQL.cn。

          最近熱文閱讀:

          1、Java8 Stream:2萬字20個(gè)實(shí)例,玩轉(zhuǎn)集合的篩選、歸約、分組、聚合
          2、公司規(guī)定所有接口都用 POST請求,這是為什么?
          3、為什么阿里強(qiáng)制 boolean 類型變量不能使用 is 開頭?
          4、面試官:InnoDB中一棵B+樹可以存放多少行數(shù)據(jù)?
          5、MyBatis批量插入幾千條數(shù)據(jù),請慎用foreach
          6、有了 for (;;) ,為什么還需要while (true) ?到底哪個(gè)更快?
          7、名企公開掛“加班真好”標(biāo)語,員工稱一年被免費(fèi)“白嫖”600多小時(shí)!網(wǎng)友看不下去了,稽查部門展開調(diào)查...
          8、面試官:為什么 Java 不把基本類型放在堆中?我竟然答不上來。。
          9、IDEA 注釋模板這樣搞!
          10、后端開掛:3行代碼寫出8個(gè)接口!

          關(guān)注公眾號(hào),你想要的Java都在這里

          瀏覽 49
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  交+视频+在线+观看 | 美女被干操的视频网站 | 大鸡吧在线免费视频 | 欧美熟妇XXXⅩ高潮交 | 五月婷婷色 |