Spring MVC如何設(shè)置響應(yīng)
本篇文章介紹響應(yīng)相關(guān)的知識(shí), 通過 Spring 來設(shè)置響應(yīng)中的值, 向客戶端返回設(shè)置好的響應(yīng).
1. 返回靜態(tài)頁(yè)面
我們首先使用 html 寫一個(gè)前端頁(yè)面, 再通過 Spring 方法, 將這個(gè) html 頁(yè)面作為響應(yīng)的內(nèi)容, 展示給用戶.
顯然, 方法返回的只是一個(gè)字符串, 并非 html 展示的頁(yè)面.
如何將 html 頁(yè)面返回給客戶端呢?? 這需要修改 類注解.
若方法返回的是一個(gè)頁(yè)面, 則需要將原來的類注解 @RestController 修改為 @Controller.
接下來, 對(duì)涉及到的幾個(gè)注解逐個(gè)進(jìn)行解釋.
1.1 Spring 默認(rèn)掃描路徑
我們知道, 每一個(gè)路徑, 都對(duì)應(yīng)了一個(gè)方法. 當(dāng)服務(wù)器收到客戶端的請(qǐng)求時(shí), Spring 就會(huì)根據(jù)請(qǐng)求中的資源路徑, 尋找該路徑對(duì)應(yīng)的方法, 進(jìn)而計(jì)算響應(yīng)結(jié)果, 最后返回響應(yīng).
而 Spring 中有大量的方法存在, 包括使用 Maven 引入的第三方庫(kù), 都存在于 Spring 中. 若 Spring 要掃描所有的方法, 一個(gè)一個(gè)的去進(jìn)行比對(duì), 確定哪個(gè)是資源路徑所對(duì)應(yīng)的方法的話, 那工作量是巨大的.
因此, Spring 有一個(gè)默認(rèn)掃描路徑: 只掃描啟動(dòng)類所在的目錄, 及其子目錄.
若請(qǐng)求中資源路徑對(duì)應(yīng)的方法, 屬于啟動(dòng)類所在目錄或子目錄時(shí), 會(huì)被 Spring 掃描到:
而當(dāng)請(qǐng)求中資源路徑所對(duì)應(yīng)的方法, 不屬于啟動(dòng)類所在目錄或子目錄時(shí), 則 Spring 不會(huì)掃描, 客戶端就會(huì)顯示錯(cuò)誤:
因此, Spring 也當(dāng)然不會(huì)掃描 Maven 中第三方庫(kù)中的方法.
有了默認(rèn)的掃描路徑, 大大降低了 Spring 的工作量, 提升了開發(fā)效率.
1.2 @RestController
雖然 Spring 有默認(rèn)的掃描路徑, 但是當(dāng)項(xiàng)目很大時(shí), 這個(gè)路徑下也是會(huì)有很多的方法存在的.
于是, 可以使用 @RestController 對(duì)類進(jìn)行標(biāo)記, Spring 只需掃描被 @RestController 標(biāo)記的類.
因此, Spring 的掃描對(duì)象為: 默認(rèn)掃描路徑中的類 && 使用 @RestController 進(jìn)行標(biāo)記的類
當(dāng)默認(rèn)路徑下的類沒有使用 @RestController 進(jìn)行標(biāo)記時(shí), 那么 Spring 也不會(huì)進(jìn)行掃描, 進(jìn)一步減少了 Spring 的工作量.
@RestController 的特性如下:
- 類注解. 只能對(duì)類進(jìn)行使用
- 存活于運(yùn)行階段. (整個(gè)項(xiàng)目運(yùn)行時(shí), 都存在)
- 包含 @Controller 和 @ResponseBody
其中, @Controller 表示返回的是頁(yè)面. @ResponseBody 表示返回的是數(shù)據(jù).
@RestController 也表示返回的是數(shù)據(jù).
由于 @RestController = @Controller + @ResponseBody, 因此, 左右兩側(cè)的注解效果相同:
1.2.1 @Controller => 返回頁(yè)面
@Controller 是一個(gè)類注解(只能給類使用), 并且使用此注解標(biāo)記類時(shí), 表示該類中的所有方法(@ResponseBody 標(biāo)記的方法除外, 見下文), 返回的均是頁(yè)面.
因此, 我們將類的注釋修改為 @Controller, 就可以返回靜態(tài)頁(yè)面了:
Spring 會(huì)以 resources.static 為該 html 文件的基準(zhǔn)路徑, 掃描指定路徑下的 html 文件, 并返回該 html 構(gòu)造的頁(yè)面. 并且, html 文件的路徑前要加上 /
不過, 現(xiàn)在后端已經(jīng)基本不會(huì)返回頁(yè)面了.
@RequestMapping("/resp") @Controller // 表示類中的方法只能返回頁(yè)面 public class RespController { @ResponseBody // 該方法可以返回?cái)?shù)據(jù) @RequestMapping("/r1") public String returnPage() { // 返回頁(yè)面時(shí), 一定要加上 / return "/index.html"; } }
1.2.2 @ResponseBody
@ResponseBody 既是一個(gè)類注解, 也是一個(gè)方法注解, 表示返回的是數(shù)據(jù).
當(dāng)類注解為 @Controller 時(shí), 類中的方法只能返回頁(yè)面, 若此時(shí)我們想返回?cái)?shù)據(jù), 可以對(duì)方法使用 @ResponseBody 進(jìn)行標(biāo)記, 被標(biāo)記的方法可以返回?cái)?shù)據(jù).
綜上, @RestController, @Controller, @ResponseBody 的使用場(chǎng)景如下:
- 一個(gè)類中, 既有返回頁(yè)面的方法, 也有返回?cái)?shù)據(jù)的方法 ==> 使用 @Controller 對(duì)類標(biāo)記, 對(duì)返回?cái)?shù)據(jù)的方法使用 @ResponseBody 標(biāo)記.
- 如果一個(gè)類中所有的方法, 返回的都是數(shù)據(jù) ==> 使用 @RestController 或者 @Controller + @ResponseBody 對(duì)類標(biāo)記
- 如果一個(gè)類中所有的方法, 返回的都是頁(yè)面 ==> 使用 @Controller 對(duì)類標(biāo)記
- 類必須有 @Controller 注解才能被 Spring 掃描到(@RestController 包含了 @Controller)
2. 返回 HTML
默認(rèn)情況下, 響應(yīng)中的 Content-Type 都是 test/html, 因此, 瀏覽器收到數(shù)據(jù)后, 都會(huì)按照 html 的格式來解析, 最終展示在頁(yè)面上.
因此, 如果我們想要給客戶端返回一個(gè) HTML 片段, 那我們無需任何操作, 直接返回 HTML 代碼即可.
// 返回 HTML 片段 @ResponseBody @RequestMapping("/r3") public String returnHTML() { return "<h1>這是一個(gè)一級(jí)標(biāo)題</h1>"; }
2.1 @RequestMapping
@RequestMapping 是一個(gè)類注解, 也是一個(gè)方法注解, 既可以對(duì)類設(shè)置路徑, 也可以對(duì)方法設(shè)置路徑.
此外, @RequestMapping 還有一些屬性.
2.1.1 produces(修改響應(yīng)的 Content-Type)
但是, 如果我們想要把這個(gè) HTML 代碼, 當(dāng)做一個(gè)普通的字符串去返回, 該怎么辦呢?
顯然, 我們將響應(yīng)的 Content-Type 類型修改為純文本格式即可, 即: test/plain
我們可以通過修改 @RequestMapping 中的 produces 屬性, 來修改 Content-Type:
這樣, 瀏覽器接收響應(yīng)后, 就會(huì)將 Body 中的內(nèi)容, 以純文本的格式來解析, 而不是當(dāng)做 HTML .
// 返回純文本 @ResponseBody @RequestMapping(value = "/r4", produces = "text/plain") // 修改 Content-Type 為純文本格式 public String returnText() { // 當(dāng)成普通字符串返回 return "<h1>這是一個(gè)一級(jí)標(biāo)題</h1>"; }
2.1.2 其他屬性
@RequestMapping 中不僅有 produces 這一屬性, 還有其他屬性. 通過設(shè)置這些屬性值, 可以對(duì)請(qǐng)求或者響應(yīng)中的內(nèi)容做出要求:
method
: 要求請(qǐng)求的方法必須是什么(如:GET, POST, ....), 否則不處理params
: 要求請(qǐng)求中必須包含哪些參數(shù), 否則不處理headers
: 要求請(qǐng)求的 header 中必須包含哪些 header 信息, 否則不處理consumes
: 要求請(qǐng)求的 Content-Type 必須是什么, 否則不處理produces
: 設(shè)置響應(yīng)的 Content-Type
3. 返回 JSON
Spring 會(huì)根據(jù)返回?cái)?shù)據(jù)的類型, 自動(dòng)對(duì) Content-Type 進(jìn)行類型的轉(zhuǎn)換.
上文提到, 當(dāng)返回的數(shù)據(jù)是字符串時(shí), 默認(rèn)的 Content-Type 是 text/html; 若想改成其他類型, 還需要手動(dòng)進(jìn)行轉(zhuǎn)換.
但是當(dāng)我們返回的數(shù)據(jù)是一個(gè)對(duì)象時(shí), Spring 會(huì)自動(dòng)將這個(gè)對(duì)象序列化為 JSON 格式, 并自動(dòng)將 Content-Type 轉(zhuǎn)換為 application/json:
// 返回 JSON @ResponseBody @RequestMapping("/r5") public UserInfo returnJson() { // 若返回的數(shù)據(jù)是一個(gè)對(duì)象 // Spring 會(huì)自動(dòng)將響應(yīng)中的 Content-Type 轉(zhuǎn)換為 JSON 格式 return new UserInfo("dings", "aaa", 1); }
4. 設(shè)置狀態(tài)碼
4.1 HttpServletResponse
在后端的 Spring 項(xiàng)目中, 我們既可以通過 HttpServletRequest 來獲取請(qǐng)求中的信息, 同樣也可以通過 HttpServletResponse 來設(shè)置響應(yīng)中的信息.
因此, 我們可以拿到 HttpServletResponse 對(duì)象, 進(jìn)而通過 setStatus 方法修改響應(yīng)中的狀態(tài)碼:
// 設(shè)置狀態(tài)碼 @ResponseBody @RequestMapping("/r6") public String setStatus(HttpServletResponse response) { // 手動(dòng)將響應(yīng)中的狀態(tài)碼設(shè)置為 404 response.setStatus(404); return "設(shè)置狀態(tài)碼成功!!"; }
注意: 狀態(tài)碼不影響頁(yè)面的展示!!
不管狀態(tài)碼是什么, 都可以返回我們自定義的內(nèi)容. 至于為什么有些網(wǎng)站的 404 頁(yè)面是一些提示內(nèi)容, 因?yàn)槟莻€(gè)界面也是維護(hù)那個(gè)網(wǎng)站的程序員自己代碼寫的.
程序員當(dāng)然也可以將 404 頁(yè)面打扮的很漂亮!! 比如 bilibili:
5. 設(shè)置 Header
后端可以設(shè)置響應(yīng)中的 header, 通過 header 來向客戶端傳遞一些信息.
仍然是通過 HttpServletResponse 設(shè)置響應(yīng)中的 header:
(header 是以鍵值對(duì)的形式存儲(chǔ)數(shù)據(jù)的)
// 設(shè)置 header @ResponseBody @RequestMapping("/r7") public String setHeader(HttpServletResponse response) { response.setHeader("myHeader", "hahaha"); return "設(shè)置 header 成功!!"; }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Kotlin基礎(chǔ)教程之函數(shù)定義與變量聲明
這篇文章主要介紹了Kotlin基礎(chǔ)教程之函數(shù)定義與變量聲明的相關(guān)資料,需要的朋友可以參考下2017-05-05使用ShardingJDBC進(jìn)行數(shù)據(jù)分片以及讀寫分離
ShardingJDBC是一個(gè)輕量級(jí)的Java框架,提供了數(shù)據(jù)分片、讀寫分離、分布式主鍵生成等數(shù)據(jù)訪問功能,本文將給大家介紹如何使用ShardingJDBC進(jìn)行數(shù)據(jù)分片以及讀寫分離,需要的朋友可以參考下2024-01-01Java網(wǎng)絡(luò)編程基礎(chǔ)用法詳解
網(wǎng)絡(luò)編程是指編寫運(yùn)行在多個(gè)設(shè)備(計(jì)算機(jī))的程序,這些設(shè)備都通過網(wǎng)絡(luò)連接起來,本文將帶大家詳細(xì)了解Java的網(wǎng)絡(luò)編程,文中有相關(guān)的代碼示例,需要的朋友可以參考下2023-05-05Java數(shù)組轉(zhuǎn)List及Stream的基本方法使用方法
Java?的?Stream?流操作是一種簡(jiǎn)潔而強(qiáng)大的處理集合數(shù)據(jù)的方式,允許對(duì)數(shù)據(jù)進(jìn)行高效的操作,如過濾、映射、排序和聚合,這篇文章主要介紹了Java數(shù)組轉(zhuǎn)List及Stream的基本方法使用教程,需要的朋友可以參考下2024-08-08java顯示當(dāng)前美國(guó)洛杉磯時(shí)間
這篇文章主要介紹了java顯示當(dāng)前美國(guó)洛杉磯時(shí)間的方法,也就是當(dāng)前時(shí)間的切換,需要的朋友可以參考下2014-02-02Spring Boot靜態(tài)資源路徑的配置與修改詳解
最近在做SpringBoot項(xiàng)目的時(shí)候遇到了“白頁(yè)”問題,通過查資料對(duì)SpringBoot訪問靜態(tài)資源做了總結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09