0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何使用Spring構(gòu)建REST服務(wù)(四)

「Spring」認(rèn)證安全架構(gòu) ? 來(lái)源:「Spring」認(rèn)證安全架構(gòu) ? 作者:「Spring」認(rèn)證安全 ? 2022-07-28 16:02 ? 次閱讀

書接上文???

不斷發(fā)展的 REST API

通過(guò)一個(gè)額外的庫(kù)和幾行額外的代碼,您已將超媒體添加到您的應(yīng)用程序中。但這并不是使您的服務(wù)成為 RESTful 所需的唯一事情。REST 的一個(gè)重要方面是它既不是技術(shù)堆棧也不是單一標(biāo)準(zhǔn)。

REST 是架構(gòu)約束的集合,采用這些約束會(huì)使您的應(yīng)用程序更具彈性。彈性的一個(gè)關(guān)鍵因素是,當(dāng)您對(duì)服務(wù)進(jìn)行升級(jí)時(shí),您的客戶不會(huì)遭受停機(jī)時(shí)間的困擾。

在“過(guò)去”的日子里,升級(jí)因破壞客戶端而臭名昭著。換句話說(shuō),升級(jí)到服務(wù)器需要更新客戶端。在當(dāng)今時(shí)代,花費(fèi)數(shù)小時(shí)甚至數(shù)分鐘進(jìn)行升級(jí)的停機(jī)時(shí)間可能會(huì)造成數(shù)百萬(wàn)美元的收入損失。

有些公司要求您向管理層提出一個(gè)計(jì)劃,以盡量減少停機(jī)時(shí)間。過(guò)去,您可以在周日凌晨 2:00 進(jìn)行升級(jí),此時(shí)負(fù)載最低。但在今天的基于互聯(lián)網(wǎng)的電子商務(wù)中,國(guó)際客戶在其他時(shí)區(qū),這樣的策略就沒有那么有效了。

基于 SOAP 的服務(wù)和基于CORBA 的服務(wù)非常脆弱。很難推出可以同時(shí)支持新舊客戶端的服務(wù)器。使用基于 REST 的實(shí)踐,這要容易得多。特別是使用 Spring 堆棧。

支持對(duì) API 的更改

想象一下這個(gè)設(shè)計(jì)問(wèn)題:您已經(jīng)推出了一個(gè)具有Employee基于此記錄的系統(tǒng)。該系統(tǒng)大受歡迎。你已經(jīng)把你的系統(tǒng)賣給了無(wú)數(shù)的企業(yè)。突然,需要拆分員工的姓名firstNamelastName出現(xiàn)。

哦哦。沒想到。

在您打開課程并用andEmployee替換單個(gè)字段之前,請(qǐng)停下來(lái)想一想。這會(huì)破壞任何客戶嗎?升級(jí)它們需要多長(zhǎng)時(shí)間。您甚至控制所有訪問(wèn)您服務(wù)的客戶端嗎?namefirstNamelastName

停機(jī)時(shí)間 = 損失金錢。管理層準(zhǔn)備好了嗎?

有一個(gè)比 REST 早幾年的舊策略。

永遠(yuǎn)不要?jiǎng)h除數(shù)據(jù)庫(kù)中的列。

— 未知

您始終可以將列(字段)添加到數(shù)據(jù)庫(kù)表中。但不要帶走一個(gè)。RESTful 服務(wù)中的原理是相同的。

將新字段添加到您的 JSON 表示中,但不要帶走任何字段。像這樣:

支持多個(gè)客戶端的 JSON

{  "id": 1,  "firstName": "Bilbo",  "lastName": "Baggins",  "role": "burglar",  "name": "Bilbo Baggins",  "_links": {    "self": {      "href": "http://localhost:8080/employees/1"    },    "employees": {      "href": "http://localhost:8080/employees"    }  }}

請(qǐng)注意此格式如何顯示firstName, lastName, AND name?雖然它包含重復(fù)信息,但其目的是同時(shí)支持新老客戶。這意味著您可以升級(jí)服務(wù)器,而無(wú)需同時(shí)升級(jí)客戶端。一個(gè)可以減少停機(jī)時(shí)間的好舉措。

您不僅應(yīng)該以“舊方式”和“新方式”顯示這些信息,還應(yīng)該以兩種方式處理傳入的數(shù)據(jù)。

如何?簡(jiǎn)單的。像這樣:

處理“舊”和“新”客戶的員工記錄

package payroll;import java.util.Objects;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;@Entityclass Employee {  private @Id @GeneratedValue Long id;  private String firstName;  private String lastName;  private String role;  Employee() {}  Employee(String firstName, String lastName, String role) {    this.firstName = firstName;    this.lastName = lastName;    this.role = role;  }  public String getName() {    return this.firstName + " " + this.lastName;  }  public void setName(String name) {    String[] parts = name.split(" ");    this.firstName = parts[0];    this.lastName = parts[1];  }  public Long getId() {    return this.id;  }  public String getFirstName() {    return this.firstName;  }  public String getLastName() {    return this.lastName;  }  public String getRole() {    return this.role;  }  public void setId(Long id) {    this.id = id;  }  public void setFirstName(String firstName) {    this.firstName = firstName;  }  public void setLastName(String lastName) {    this.lastName = lastName;  }  public void setRole(String role) {    this.role = role;  }  @Override  public boolean equals(Object o) {    if (this == o)      return true;    if (!(o instanceof Employee))      return false;    Employee employee = (Employee) o;    return Objects.equals(this.id, employee.id) && Objects.equals(this.firstName, employee.firstName)        && Objects.equals(this.lastName, employee.lastName) && Objects.equals(this.role, employee.role);  }  @Override  public int hashCode() {    return Objects.hash(this.id, this.firstName, this.lastName, this.role);  }  @Override  public String toString() {    return "Employee{" + "id=" + this.id + ", firstName='" + this.firstName + '\'' + ", lastName='" + this.lastName        + '\'' + ", role='" + this.role + '\'' + '}';  }}

這個(gè)類與以前版本的Employee. 讓我們回顧一下變化:

  • 字段name已替換為firstNamelastName。
  • 定義了舊name屬性的“虛擬”吸氣劑。getName()它使用firstNameandlastName字段來(lái)產(chǎn)生一個(gè)值。
  • name還定義了舊屬性的“虛擬”設(shè)置器, setName(). 它解析傳入的字符串并將其存儲(chǔ)到適當(dāng)?shù)淖侄沃小?/li>

當(dāng)然,并非對(duì) API 的每一次更改都像拆分字符串或合并兩個(gè)字符串一樣簡(jiǎn)單。但是對(duì)于大多數(shù)場(chǎng)景來(lái)說(shuō),想出一組轉(zhuǎn)換肯定不是不可能的,對(duì)吧?

不要忘記更改預(yù)加載數(shù)據(jù)庫(kù)的方式(在 中LoadDatabase)以使用這個(gè)新的構(gòu)造函數(shù)。

log.info("Preloading " + repository.save(new Employee("Bilbo", "Baggins", "burglar")));

log.info("Preloading " + repository.save(new Employee("Frodo", "Baggins", "thief")));

適當(dāng)?shù)姆磻?yīng)

朝著正確方向邁出的另一個(gè)步驟是確保您的每個(gè) REST 方法都返回正確的響應(yīng)。像這樣更新 POST 方法:

處理“舊”和“新”客戶端請(qǐng)求的 POST

@PostMapping("/employees")ResponseEntity newEmployee(@RequestBody Employee newEmployee) {  EntityModel entityModel = assembler.toModel(repository.save(newEmployee));  return ResponseEntity //      .created(entityModel.getRequiredLink(IanaLinkRelations.SELF).toUri()) //      .body(entityModel);}復(fù)制
  • Employee對(duì)象像以前一樣保存。但是生成的對(duì)象使用EmployeeModelAssembler.
  • Spring MVCResponseEntity用于創(chuàng)建HTTP 201 Created狀態(tài)消息。這種類型的響應(yīng)通常包含一個(gè)Location響應(yīng)頭,我們使用從模型的自相關(guān)鏈接派生的 URI。
  • 此外,返回已保存對(duì)象的基于模型的版本。

通過(guò)這些調(diào)整,您可以使用相同的端點(diǎn)來(lái)創(chuàng)建新的員工資源,并使用遺留name字段:

$ curl -v -X POST localhost:8080/employees -H 'Content-Type:application/json' -d '{"name": "Samwise Gamgee", "role": "gardener"}'

輸出如下所示:

> POST /員工 HTTP/1.1> 主機(jī):本地主機(jī):8080> 用戶代理:curl/7.54.0> 接受:*/*> 內(nèi)容類型:應(yīng)用程序/json> 內(nèi)容長(zhǎng)度:46>< 位置:http://localhost:8080/employees/3< 內(nèi)容類型:application/hal+json;charset=UTF-8< 傳輸編碼:分塊< 日期:格林威治標(biāo)準(zhǔn)時(shí)間 2018 年 8 月 10 日星期五 19:44:43<{  “身份證”:3,  "firstName": "Samwise",  "lastName": "Gamgee",  “角色”:“園丁”,  "name": "Samwise Gamgee",  “_鏈接”:{    “自己”: {      “href”:“http://localhost:8080/employees/3”    },    “雇員”: {      "href": "http://localhost:8080/employees"    }  }}

這不僅使生成的對(duì)象在 HAL(name以及firstName/ lastName)中呈現(xiàn),而且Location標(biāo)頭也填充了
http://localhost:8080/employees/3. 超媒體驅(qū)動(dòng)的客戶端可以選擇“沖浪”到這個(gè)新資源并繼續(xù)與之交互。

PUT 控制器方法需要類似的調(diào)整:

為不同的客戶端處理 PUT

@PutMapping("/employees/{id}")ResponseEntity replaceEmployee(@RequestBody Employee newEmployee, @PathVariable Long id) {  Employee updatedEmployee = repository.findById(id) //      .map(employee -> {        employee.setName(newEmployee.getName());        employee.setRole(newEmployee.getRole());        return repository.save(employee);      }) //      .orElseGet(() -> {        newEmployee.setId(id);        return repository.save(newEmployee);      });  EntityModel entityModel = assembler.toModel(updatedEmployee);  return ResponseEntity //      .created(entityModel.getRequiredLink(IanaLinkRelations.SELF).toUri()) //      .body(entityModel);}復(fù)制

然后使用 將操作Employee構(gòu)建的對(duì)象包裝到一個(gè)對(duì)象中。使用該方法,您可以檢索由rel創(chuàng)建的。這個(gè)方法返回一個(gè)必須用方法變成一個(gè)的。save()
EmployeeModelAssemblerEntityModelgetRequiredLink()LinkEmployeeModelAssemblerSELFLinkURItoUri

由于我們想要一個(gè)比200 OK更詳細(xì)的 HTTP 響應(yīng)代碼,我們將使用 Spring MVC 的ResponseEntity包裝器。它有一個(gè)方便的靜態(tài)方法created(),我們可以在其中插入資源的 URI。HTTP 201 Created是否具有正確的語(yǔ)義值得商榷,因?yàn)槲覀儾灰欢ㄒ皠?chuàng)建”新資源。但它預(yù)裝了一個(gè)Location響應(yīng)頭,所以用它運(yùn)行。

$ curl -v -X PUT localhost:8080/employees/3 -H 'Content-Type:application/json' -d '{"name": "Samwise Gamgee", "role": "ring bearer"}'* TCP_NODELAY 設(shè)置* 連接到 localhost (::1) 端口 8080 (#0)> PUT /employees/3 HTTP/1.1> 主機(jī):本地主機(jī):8080> 用戶代理:curl/7.54.0> 接受:*/*> 內(nèi)容類型:應(yīng)用程序/json> 內(nèi)容長(zhǎng)度:49>< HTTP/1.1 201< 位置:http://localhost:8080/employees/3< 內(nèi)容類型:application/hal+json;charset=UTF-8< 傳輸編碼:分塊< 日期:格林威治標(biāo)準(zhǔn)時(shí)間 2018 年 8 月 10 日星期五 19:52:56{“身份證”:3,"firstName": "Samwise","lastName": "Gamgee",“角色”:“戒指持有者”,"name": "Samwise Gamgee",“_鏈接”:{“自己”: {“href”:“http://localhost:8080/employees/3”},“雇員”: {"href": "http://localhost:8080/employees"}}}

該員工資源現(xiàn)已更新,并且位置 URI 已發(fā)回。最后,適當(dāng)?shù)馗?DELETE 操作:

處理 DELETE 請(qǐng)求

@DeleteMapping("/employees/{id}")ResponseEntity deleteEmployee(@PathVariable Long id) {  repository.deleteById(id);  return ResponseEntity.noContent().build();}復(fù)制

這將返回HTTP 204 No Content響應(yīng)。

$ curl -v -X 刪除本地主機(jī):8080/employees/1* TCP_NODELAY 設(shè)置* 連接到 localhost (::1) 端口 8080 (#0)> 刪除 /employees/1 HTTP/1.1> 主機(jī):本地主機(jī):8080> 用戶代理:curl/7.54.0> 接受:*/*>< HTTP/1.1 204< 日期:格林威治標(biāo)準(zhǔn)時(shí)間 2018 年 8 月 10 日星期五 21:30:26

對(duì)類中的字段進(jìn)行更改Employee需要與您的數(shù)據(jù)庫(kù)團(tuán)隊(duì)協(xié)調(diào),以便他們可以正確地將現(xiàn)有內(nèi)容遷移到新列中。

您現(xiàn)在已準(zhǔn)備好進(jìn)行升級(jí),不會(huì)干擾現(xiàn)有客戶端,而新客戶端可以利用這些增強(qiáng)功能!

順便說(shuō)一句,您是否擔(dān)心通過(guò)網(wǎng)絡(luò)發(fā)送太多信息?在某些每個(gè)字節(jié)都很重要的系統(tǒng)中,API 的發(fā)展可能需要退居二線。但是在你測(cè)量之前不要追求這種過(guò)早的優(yōu)化。


以上就是今天關(guān)于Spring的一些討論,對(duì)你有幫助嗎?如果你有興趣深入了解,歡迎到Spring中國(guó)教育管理中心留言交流!

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    340

    瀏覽量

    14356
  • REST
    +關(guān)注

    關(guān)注

    0

    文章

    32

    瀏覽量

    9422
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    如何用ACM簡(jiǎn)化你的Spring Cloud微服務(wù)環(huán)境配置管理

    摘要: 本文我們就如何使用阿里云ACM這樣的配置管理產(chǎn)品在Spring Cloud中替代Spring Cloud Config幫助簡(jiǎn)化環(huán)境配置管理做一個(gè)簡(jiǎn)單的示例,幫助你理解基于ACM來(lái)簡(jiǎn)化微服務(wù)
    發(fā)表于 02-02 14:18

    使用阿里云ACM簡(jiǎn)化你的Spring Cloud微服務(wù)環(huán)境配置管理

    摘要: 本文我們就如何使用阿里云ACM這樣的配置管理產(chǎn)品在Spring Cloud中替代Spring Cloud Config幫助簡(jiǎn)化環(huán)境配置管理做一個(gè)簡(jiǎn)單的示例,幫助你理解基于ACM來(lái)簡(jiǎn)化微服務(wù)
    發(fā)表于 07-04 17:16

    Spring Boot嵌入式Web容器原理是什么

    Spring Boot嵌入式Web容器原理Spring Boot的目標(biāo)是構(gòu)建“非常容易創(chuàng)建、獨(dú)立、產(chǎn)品級(jí)別的基于Spring的應(yīng)用”。這些應(yīng)用是“立即可運(yùn)行的”。在這個(gè)過(guò)程中,完全沒有
    發(fā)表于 12-16 07:57

    REST端口支持構(gòu)建動(dòng)態(tài)REST請(qǐng)求來(lái)使用RESTful API網(wǎng)絡(luò)

    REST端口支持構(gòu)建動(dòng)態(tài)REST請(qǐng)求來(lái)使用RESTful API網(wǎng)絡(luò)服務(wù)。 概覽 REST端口暴露了一個(gè)簡(jiǎn)單的接口來(lái)為
    的頭像 發(fā)表于 01-17 09:11 ?4866次閱讀

    REST API是什么,如何使用REST端口

    /服務(wù)器) 模型對(duì)資源進(jìn)行增刪改查操作。而其中客戶端和服務(wù)器是分離的,而知行之橋中的REST端口就是作為REST API中的客戶端,對(duì)服務(wù)
    的頭像 發(fā)表于 02-17 18:00 ?9350次閱讀
    <b class='flag-5'>REST</b> API是什么,如何使用<b class='flag-5'>REST</b>端口

    Spring REST Docs RESTful服務(wù)文檔

    ./oschina_soft/spring-restdocs.zip
    發(fā)表于 05-24 09:31 ?1次下載
    <b class='flag-5'>Spring</b> <b class='flag-5'>REST</b> Docs RESTful<b class='flag-5'>服務(wù)</b>文檔

    Spring認(rèn)證是什么?

    ,例如:配置、組件掃描、AOP、數(shù)據(jù)訪問(wèn)和事務(wù)、REST、安全、自動(dòng)配置、執(zhí)行器、 Spring boot測(cè)試等。
    的頭像 發(fā)表于 07-04 10:19 ?1335次閱讀
    <b class='flag-5'>Spring</b>認(rèn)證是什么?

    如何獲得Spring認(rèn)證?學(xué)習(xí)JAVA如何獲得Spring Professional認(rèn)證?

    、組件掃描、AOP、數(shù)據(jù)訪問(wèn)和事務(wù)、REST、安全、自動(dòng)配置、執(zhí)行器、 Spring boot測(cè)試等。 1)參加Spring中國(guó)教育管理中心授權(quán)合作伙伴Spring培訓(xùn)課程 2)報(bào)名考
    的頭像 發(fā)表于 07-04 10:20 ?1829次閱讀
    如何獲得<b class='flag-5'>Spring</b>認(rèn)證?學(xué)習(xí)JAVA如何獲得<b class='flag-5'>Spring</b> Professional認(rèn)證?

    spring認(rèn)證證書有用嗎?

    :配置、組件掃描、AOP、數(shù)據(jù)訪問(wèn)和事務(wù)、REST、安全、自動(dòng)配置、執(zhí)行器、 Spring boot測(cè)試等。 目前Spring認(rèn)證的版本:Spring v5.0(VMware EDU-
    的頭像 發(fā)表于 07-12 15:59 ?2240次閱讀

    如何使用Spring構(gòu)建REST服務(wù)(一)

    關(guān)于 REST 如何適應(yīng)微服務(wù)世界還有一個(gè)更大的討論,但是——對(duì)于本教程——讓我們看看構(gòu)建 RESTful 服務(wù)
    的頭像 發(fā)表于 07-28 15:59 ?918次閱讀

    如何使用Spring構(gòu)建REST服務(wù)(二)

    要使用 Web 層次包裝您的存儲(chǔ)庫(kù),您必須使用 Spring MVC。多虧了 Spring Boot,代碼基礎(chǔ)設(shè)施很少。相反,我們可以專注于行動(dòng)。
    的頭像 發(fā)表于 07-28 16:00 ?753次閱讀

    如何使用Spring構(gòu)建REST服務(wù)(三)

    到目前為止,您擁有一個(gè)基于 Web 服務(wù)來(lái)處理涉及員工數(shù)據(jù)的核心操作。但這還不足以讓事情變得“RESTful”。
    的頭像 發(fā)表于 07-28 16:01 ?863次閱讀

    如何使用Spring構(gòu)建REST服務(wù)(五)

    到目前為止,您已經(jīng)使用基本鏈接構(gòu)建了一個(gè)可進(jìn)化的 API。為了發(fā)展您的 API 并更好地為您的客戶服務(wù),您需要接受超媒體作為應(yīng)用程序狀態(tài)引擎的概念。
    的頭像 發(fā)表于 07-28 16:03 ?866次閱讀

    REST的6大指導(dǎo)原則

    systems )架構(gòu)風(fēng)格。由Roy Fielding 提出。 REST API 也稱RESTful API, 其遵循REST架構(gòu)規(guī)范的應(yīng)用編程接口, 支持與RESTful WEB服務(wù)進(jìn)行交互。簡(jiǎn)單來(lái)講就是
    的頭像 發(fā)表于 10-09 14:27 ?1614次閱讀

    Spring Cloud :打造可擴(kuò)展的微服務(wù)網(wǎng)關(guān)

    Spring Cloud Gateway是一個(gè)基于Spring Framework 5和Project Reactor的反應(yīng)式編程模型的微服務(wù)網(wǎng)關(guān)。它提供了豐富的功能,包括動(dòng)態(tài)路由、請(qǐng)求限流、集成安全性等,使其成為
    的頭像 發(fā)表于 10-22 10:03 ?537次閱讀
    <b class='flag-5'>Spring</b> Cloud :打造可擴(kuò)展的微<b class='flag-5'>服務(wù)</b>網(wǎng)關(guān)