Spring Start Here 讀書筆記:第10章 Implementing REST services

REST 服務可用于實現兩個應用之間的通訊,包括 Web 應用中的客戶端和服務器之間,移動應用與后端服務之間,或兩個后端服務之間。

10.1 使用 REST 服務在應用之間交換數據

REST端點是應用程序通過 Web 協議公開服務的方式,因此也稱為 Web 服務。

在 Spring 中,REST 端點仍然是映射到 HTTP 方法和路徑的控制器操作。但對于 REST 服務, Spring MVC 調度器 servlet 不會查找視圖,服務器在 HTTP 響應中直接向客戶端返回控制器操作的返回內容。

REST 端點需注意以下問題:

  • 如果控制器的操作需要很長時間才能完成,對端點的 HTTP 調用可能會超時并中斷通信。
  • 不建議在一次調用中發送大量數據(例如幾兆字節),可能會導致調用超時并中斷通信。
  • 端點上過多的并發調用可能導致應用失敗。
  • REST 端點調用可能因為網絡原因而失敗。

總之,要考慮對失效情況的處理。作者推薦了J. J. Geewax的API Design
Patterns (Manning, 2021)一書。

10.2 實現 REST 端點

Spring 在 REST 端點后面使用相同的 Spring MVC 機制。

看一下示例sq-ch10-ex1。本例非常簡單,沒有HTML文件,只有一個控制類HelloController :

@Controller
public class HelloController {@GetMapping("/hello")@ResponseBodypublic String hello() {return "Hello!";}@GetMapping("/ciao")@ResponseBodypublic String ciao() {return "Ciao!";}
}

注解@Controller和@GetMapping上一章都講過了,唯一新的注解是@ResponseBody。它的作用是告知調度 servlet,控制器的操作不會返回視圖名稱,而是直接在 HTTP 響應中發送數據。

本例和后續示例需要安裝postman:
在這里插入圖片描述
或者也可以命令行工具cURL(Ciao是意大利語的Hello):

$ curl http://localhost:8080/hello
Hello!
$ curl -X GET http://localhost:8080/ciao
Ciao!

示例sq-ch10-ex2和上例的效果完全一樣,只不過使用注解@RestController,他是@Controller 和 @ResponseBody 的組合。

@RestController
public class HelloController {@GetMapping("/hello")public String hello() {return "Hello!";}@GetMapping("/ciao")public String ciao() {return "Ciao!";}
}

10.3 管理 HTTP 響應

HTTP 響應是指后端應用根據客戶端請求將數據返回給客戶端的方式,包含以下數據:

  • 響應頭:響應中的短數據片段(通常不超過幾個字)
  • 響應正文:返回的大量數據
  • 響應狀態

此處建議閱讀附錄C:HTTP簡介。

10.3.1 將對象作為響應主體發送

示例sq-ch10-ex3和上例非常類似,只不過返回值從字符串變為對象(此對象也稱為DTO,即data transfer object)。

看一下控制類:

@RestController
public class CountryController {@GetMapping("/france")public Country france() {Country c = Country.of("France", 67);return c;}@GetMapping("/all")public List<Country> countries() {Country c1 = Country.of("France", 67);Country c2 = Country.of("Spain", 47);return List.of(c1,c2);}
}

應用運行如下:

$ curl http://localhost:8080/all
[{"name":"France","population":67},{"name":"Spain","population":47}]$ curl http://localhost:8080/france
{"name":"France","population":67}

返回的對象為JSON格式。使用 REST 端點時,JSON 是最常見的對象表示方式(當然你也可以用XML或YAML)。此處建議閱讀附錄D:使用 JSON 格式。

10.3.2 設置響應狀態和標頭

在某些情況下,會要求自定義 HTTP 響應狀態,其最簡單、最常用的方法是使用 ResponseEntity 類。Spring 提供的這個類允許您指定 HTTP 響應的主體、狀態和標頭。詳見示例sq-ch10-ex4

model類和上例一樣,控制類變為如下:

@RestController
public class CountryController {@GetMapping("/france")public ResponseEntity<Country> france() {Country c = Country.of("France", 67);return ResponseEntity.status(HttpStatus.ACCEPTED).header("continent", "Europe").header("capital", "Paris").header("favorite_food", "cheese and wine").body(c);}
}

程序運行如下:

$ curl -v http://localhost:8080/france
* Host localhost:8080 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8080...
* Connected to localhost (::1) port 8080
* using HTTP/1.x
> GET /france HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.12.1
> Accept: */*
>
< HTTP/1.1 202
< continent: Europe
< capital: Paris
< favorite_food: cheese and wine
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Sun, 03 Aug 2025 13:02:47 GMT
<
{"name":"France","population":67}* Connection #0 to host localhost left intact

其中202對應HttpStatus.ACCEPTED。

postman運行輸出如下:
在這里插入圖片描述

10.3.3 在端點級別管理異常

在很多情況下,我們會使用異常來指示特定情況,其中一些與業務邏輯相關。在這種情況下,您可能需要在 HTTP 響應中設置一些詳細信息,以告知客戶端發生的具體情況。管理異常的方法之一是在控制器的操作中捕獲異常,并使用ResponseEntity 類,在發生異常時發送不同的響應配置。

參見示例sq-ch10-ex5。來看一下控制類的主體部分:

@PostMapping("/payment")public ResponseEntity<?> makePayment() {try {PaymentDetails paymentDetails = paymentService.processPayment();return ResponseEntity.status(HttpStatus.ACCEPTED).body(paymentDetails);} catch (NotEnoughMoneyException e) {ErrorDetails errorDetails = new ErrorDetails();errorDetails.setMessage("Not enough money to make the payment.");return ResponseEntity.badRequest().body(errorDetails);}}

運行輸出如下:

$ curl -X POST http://localhost:8080/payment
{"message":"Not enough money to make the payment."}

上述錯誤處理方法雖然可行,但在更復雜的應用程序中,將異常管理分離處理會更方便。這樣可以減少重復代碼,因為有時同一個異常可能被多個端點復用。其次,當你需要理解特定情況的工作原理時,知道在一個地方找到所有異常邏輯會更方便。因此,推薦使用 REST 控制器建議,這是一個可以攔截控制器操作拋出的異常并根據攔截到的異常應用自定義邏輯的切面。

在示例sq-ch10-ex6中,控制類PaymentController不再進行異常處理,因此代碼大大簡化:

@RestController
public class PaymentController {private final PaymentService paymentService;public PaymentController(PaymentService paymentService) {this.paymentService = paymentService;}@PostMapping("/payment")public ResponseEntity<PaymentDetails> makePayment() {PaymentDetails paymentDetails = paymentService.processPayment();return ResponseEntity.status(HttpStatus.ACCEPTED).body(paymentDetails);}
}

錯誤處理的工作由advice類ExceptionControllerAdvice 專門負責:

@RestControllerAdvice
public class ExceptionControllerAdvice {@ExceptionHandler(NotEnoughMoneyException.class)public ResponseEntity<ErrorDetails> exceptionNotEnoughMoneyHandler() {ErrorDetails errorDetails = new ErrorDetails();errorDetails.setMessage("Not enough money to make the payment.");return ResponseEntity.badRequest().body(errorDetails);}
}

輸出和上例一樣。

10.4 使用請求主體從客戶端獲取數據

前面已經使用HTTP 請求參數從客戶端到服務器傳輸少量數據,傳輸大量數據則可以用HTTP 請求正文(request body)。

要使用請求正文,只需使用 @RequestBody 注解控制器操作的參數即可。默認情況下,Spring 會假定您使用 JSON 來表示注解的參數,并嘗試將 JSON 字符串解碼為參數類型的實例。如果無法將 JSON 格式的字符串解碼為該類型,應用將返回狀態為“400 Bad Request”的響應。

參見示例sq-ch10-ex7。核心代碼為控制類:

@RestController
public class PaymentController {private static Logger logger =Logger.getLogger(PaymentController.class.getName());@PostMapping("/payment")public ResponseEntity<PaymentDetails> makePayment(@RequestBody PaymentDetails paymentDetails) {logger.info("Received payment " + paymentDetails.getAmount());return ResponseEntity.status(HttpStatus.ACCEPTED).body(paymentDetails);}
}

程序輸出如下:

$ curl -X POST http://127.0.0.1:8080/payment -d '{"amount": 1000}' -H "Content-Type: application/json"
{"amount":1000.0}

HTTP GET也支持請求正文,詳見RFC 7231。

總結

  • 表述性狀態轉移 (REST) Web 服務是在兩個應用程序之間建立通信的一種簡單方法。
  • 在 Spring 應用中,Spring MVC 機制支持 REST 端點的實現。您需要使用 @ResponseBody 注解來指定方法直接返回響應主體,或者將 @Controller 注解替換為 @RestController 來實現 REST 端點。如果您不使用上述任何一種注解,調度器 Servlet 將假定控制器的方法返回的是視圖名稱,并嘗試查找該視圖。
  • 您可以讓控制器的操作直接返回 HTTP 響應主體,并依賴 Spring 默認的 HTTP 狀態行為。
  • 您可以通過讓控制器的操作返回 ResponseEntity 實例來管理 HTTP 狀態和標頭。
  • 管理異常的一種方法是直接在控制器的操作級別處理它們。這種方法將處理異常的邏輯與特定的控制器操作耦合在一起。有時,使用這種方法會導致代碼重復,最好避免這種情況。
  • 您可以直接在控制器的操作中管理異常,或者使用 REST 控制器建議類來分離控制器的操作拋出異常時執行的邏輯。
  • 端點可以通過 HTTP 請求中的請求參數、路徑變量或 HTTP 請求正文從客戶端獲取數據。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/94227.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/94227.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/94227.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SYBASE ASE、Oracle、MySQL/MariaDB、SQL Server及PostgreSQL在郵件/短信發送功能上的全面橫向對比報告

以下是對SYBASE ASE、Oracle、MySQL/MariaDB、SQL Server及PostgreSQL在郵件/短信發送功能上的全面橫向對比報告&#xff08;截至2025年8月最新版本&#xff09;&#xff0c;涵蓋技術實現、配置復雜度、適用場景及權威評測&#xff1a;??一、郵件發送能力對比????1. Orac…

服務器與客戶端

目錄 一、服務器&#xff08;Server&#xff09; 核心特點 常見類型 二、客戶端&#xff08;Client&#xff09; 核心特點 常見類型 客戶端與服務器的交互流程 補充&#xff1a;與 “對等網絡&#xff08;P2P&#xff09;” 的區別 C/S模式 一、C/S 模式的核心原理 …

GaussDB 并發自治事務數達到最大值處理案例

1 業務背景自治事務&#xff08;Autonomous Transactions&#xff09;是一種高級特性&#xff0c;允許你在一個事務中執行另一個獨立的事務。這種機制特別有用&#xff0c;尤其是在需要在一個事務中執行多個操作但又不想因為其中一個操作失敗而影響整個事務的場景。2 業務影響在…

【傳奇開心果系列】Flet分頁自定義組件CustomPaginationComponent封裝版自定義模板

Flet分頁自定義組件CustomPaginationComponent封裝版自定義模板一、效果展示GIF動圖二、應用場景三、特色說明四、源碼下載地址一、效果展示GIF動圖 二、應用場景 圖片瀏覽應用&#xff1a; 用戶可以通過分頁組件瀏覽多張圖片&#xff0c;每點擊一次“上一頁”或“下一頁”按鈕…

數據安全——39頁解讀數字化轉型大數據安全基礎培訓方案【附全文閱讀】

適應人群為企業數據安全管理人員、IT 運維人員、數字化轉型決策者、網絡安全工程師及關注大數據安全的從業人員。主要內容圍繞數字化轉型中大數據安全展開,核心包括基礎概念(信息、數據與大數據的定義及區別,大數據 4V 特點與來源);安全風險(企業面臨的數據資產管理缺失、…

week3-[二維數組]小方塊

week3-[二維數組]小方塊 題目描述 如果四個數 a,b,c,da,b,c,da,b,c,d 可以分成兩組&#xff0c;每組兩個數&#xff0c;滿足每組里面的兩個數一樣&#xff0c;那么稱這四個數是好的。 比如&#xff0c;2,5,2,52,5,2,52,5,2,5 是好的&#xff0c;因它滿足兩組&#xff1a;222 與…

Swift 項目結構詳解:構建可維護的大型應用

Swift 項目結構詳解&#xff1a;構建可維護的大型應用一、基礎結構&#xff08;推薦新手使用&#xff09;二、組件化結構&#xff08;企業級應用推薦&#xff09;層級架構&#xff1a;MVVM Coordinator路由實現&#xff08;Coordinator模式&#xff09;三、通用組件實現DI&…

【實時Linux實戰系列】基于實時Linux的數字轉換器設計

在現代電子系統中&#xff0c;數字轉換器&#xff08;如模數轉換器ADC和數模轉換器DAC&#xff09;扮演著至關重要的角色。它們負責將模擬信號轉換為數字信號&#xff0c;或將數字信號轉換為模擬信號&#xff0c;從而實現信號的數字化處理和傳輸。在實時系統中&#xff0c;如工…

FastTracker:實時準確的視覺跟蹤

摘要 https://arxiv.org/pdf/2508.14370 傳統的多目標跟蹤(MOT)系統主要設計用于行人跟蹤&#xff0c;通常對其他物體類別的泛化能力有限。本文提出了一種能夠處理多種物體類型的通用跟蹤框架&#xff0c;特別強調在復雜交通場景中的車輛跟蹤。所提出的1方法包含兩個關鍵組件&a…

國產輕量級桌面GIS軟件Snaplayers從入門到精通(20)

國產輕量級桌面GIS軟件Snaplayers實操&#xff1a;打開圖層并顯示屬性信息1、根據數據格式選擇圖層文件2、加載圖層到地圖中&#xff0c;并在左側顯示圖層的屬性表格3、屬性表格分頁顯示Snaplayers研發團隊承諾&#xff1a;國產輕量級桌面GIS軟件Snaplayers永久免費并持續更新

快速入門flask應用(從入門到實戰)

目錄 前言&#xff1a; 了解一些網絡通信的概念 什么是網絡通信&#xff1a; 當我們訪問一個網址的時候發生了什么&#xff1a; 1. 解析 URL&#xff1a;明確訪問目標 2. DNS 域名解析&#xff1a;將 “名字” 轉為 “地址” 3. 建立連接&#xff1a;TCP 三次握手&#x…

C++/QT 開發技能樹詳解

一、 編程語言 (C)1. C基礎語法&#xff08;數據類型、模板、命名空間&#xff09;是什么&#xff1a; 這是構建C程序的基石。數據類型定義了變量存儲的數據種類和大小&#xff1b;模板允許編寫與數據類型無關的通用代碼&#xff1b;命名空間用于避免大型項目中的名稱沖突。如何…

Java多線程進階-死鎖與面試題解析

文章目錄Java多線程進階&#xff1a;死鎖與面試題解析一、并發編程的噩夢——死鎖1. 什么是死鎖&#xff1f;四個缺一不可的條件2. 如何避免死鎖&#xff1f;從破壞循環等待開始二、并發編程面試題全景解析1. 鎖與同步機制2. CAS 與原子操作3. JUC 工具與線程池4. 線程安全集合…

ZYNQ啟動流程——ZYNQ學習筆記11

ZYNQ SoC 的啟動由片上的 BootROM 開始。片上 BootROM 是 ZYNQ 芯片上的一塊非易失性存儲器&#xff0c;它包含了 ZYNQ 所支持的配置器件的驅動&#xff0c; 而且里面的代碼是不可修改的。 BootROM 中的代碼首先會在片外的非易失性存儲器中尋找一個頭文件&#xff0c; 頭文件里…

C++利用CerateProcess創建WPF進程并通過命名管道通訊

引言原因是我需要在C程序中調用另外一個WPF窗體打開或則關閉&#xff0c;進程之前通過通訊協議進行交互。由于使用不同語言開發&#xff0c;兩者都比較復雜不方便重寫&#xff0c;最方便的方法就是使用進程間通信&#xff0c;WPF窗體應用程序根據消息進行Show/Hide/Exit操作。函…

Seaborn數據可視化實戰

1. Seaborn基礎與實踐&#xff1a;數據可視化的藝術 2. Seaborn入門&#xff1a;環境搭建與基礎操作 3. Seaborn基礎圖表繪制入門 4. Seaborn數據可視化基礎&#xff1a;從內置數據集到外部數據集的應用 5. Seaborn顏色與樣式定制教程 6. Seaborn數據可視化入門&#xff1a;繪制…

BIM+寫實數字孿生落地實戰指南

&#x1f31f; 正文 在智慧城市與工業4.0的浪潮中&#xff0c;BIM與數字孿生的深度碰撞正在重塑建筑的生命周期。基于Revit&#xff08;RVT&#xff09;模型構建的超寫實數字孿生體&#xff0c;不僅實現物理空間的毫米級鏡像&#xff0c;更通過實時數據驅動&#xff0c;賦予建…

[Git] 如何拉取 GitHub 倉庫的特定子目錄

作為開發者&#xff0c;我們經常遇到只需要克隆大型倉庫中某個子目錄的場景。 Git 本身并不支持直接克隆子目錄&#xff0c;但通過一些技巧可以實現類似效果。本文將介紹幾種實用的方法&#xff0c;幫助獲取目標代碼。 為什么需要局部拉取&#xff1f; 節省時間和帶寬&#xff…

修復Simulink到UE5丟包時被控船體的殘影問題

提問 simulink 有一個和UE5協同的模塊&#xff0c;叫做Simulation 3D Scence Configuration&#xff0c;還有一個發送來自simulink到UE5數據的模塊叫做Simulation 3D Message。 現在遇到的問題是&#xff0c;這兩個模塊的優先級設置是正確的&#xff0c;且sample time都設置為0…

嵌入式第三十五課!!Linux下的網絡編程

一、目的網絡編程的目的實際上也是進程通信的一種方式&#xff0c;不過它可以在不同的主機上進行通信&#xff1b;二、需要解決的問題1. 主機與主機之間物理層面必須互聯互通。指的是參與通信的計算機&#xff08;主機&#xff09;需要通過物理設備建立連接&#xff08;光纖、網…