1. Spring MVC 中 HttpMessageConverter 轉換器
@
- 1. Spring MVC 中 HttpMessageConverter 轉換器
- 2. 補充:什麼是 HTTP 訊息
- 3. 轉換器
- 3.1 轉換器轉換的是什麼
- 4. Spring MVC中的 AJAX 請求
- 5. @ResponseBody 將伺服器端的 return 返回值轉化為“字串(JSON格式的字串)”再返回給客戶端
- 6. 補充:@RestController = (@Controller + @ResponseBody )
- 7. @RequestBody 將前端的請求體的資訊轉換Java程式中的 POJO物件
- 7.1 MappingJackson2HttpMessageConverter 將前端提交的 JSON 格式的字串,轉換為 Java程式中的POJO物件
- 8. RequestEntity 類
- 9. ResponseEntity 類
- 10. 總結:
- 11. 最後:
2. 補充:什麼是 HTTP 訊息
HTTP 訊息其實就是 HTTP 協議。HTTP 協議包括 請求協議
和 響應協議
。
以下是一份HTTP POST請求協議:
POST /springmvc/user/login HTTP/1.1 --請求行
Content-Type: application/x-www-form-urlencoded --請求頭
Content-Length: 32
Host: www.example.com
User-Agent: Mozilla/5.0
Connection: Keep-Alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
--空白行
username=admin&password=1234 --請求體
以下是一份HTTP GET請求協議:
GET /springmvc/user/del?id=1&name=zhangsan HTTP/1.1 --請求行
Host: www.example.com --請求頭
User-Agent: Mozilla/5.0
Connection: Keep-Alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
以下是一份HTTP響應協議:
HTTP/1.1 200 OK --狀態行
Date: Thu, 01 Jul 2021 06:35:45 GMT --響應頭
Content-Type: text/plain; charset=utf-8
Content-Length: 12
Connection: keep-alive
Server: Apache/2.4.43 (Win64) OpenSSL/1.1.1g
--空白行
<!DOCTYPE html> --響應體
<html>
<head>
<title>hello</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
3. 轉換器
HttpMessageConverter
是 Spring MVC
中非常重要的一個介面。翻譯為:HTTP訊息轉換器。
該介面下提供了很多實現類,不同的實現類有不同的轉換方式。
3.1 轉換器轉換的是什麼
轉換的是
HTTP協議
與Java程式中的物件
之間的互相轉換。請看下圖:
上圖是我們之前經常寫的程式碼。請求體中的資料是如何轉換成 user 物件的,底層實際上使用了
HttpMessageConverter
介面的其中的一個實現類FormHttpMessageConverter
。透過上圖可以看出
FormHttpMessageConverter
是負責將請求協議
轉換為Java物件
的。
上圖的程式碼也是之前我們經常寫的,Controller 返回值看做邏輯檢視名稱,檢視解析器將其轉換成物理檢視名稱,生成檢視物件,
StringHttpMessageConverter
負責將檢視物件中的 HTML 字串寫入到 HTTP協議的響應體中。最終完成響應。透過上圖可以看出
StringHttpMessageConverter
是負責將Java物件
轉換為響應協議
的。
透過以上內容的學習,大家應該能夠了解到 HttpMessageConverter
介面是用來做什麼的了:
如上圖所示:HttpMessageConverter 介面的可以將請求協議轉換成 Java物件;也可以把 Java物件轉換為響應協議。
HttpMessageConverter 是介面,Spring MVC 幫我們提供了非常多而豐富的實現類。每個實現類都有自己不同的轉換風格。
對於我們程式設計師來說,Spring MVC 已經幫助我們寫好了,我們只需要在不同的業務場景下,選擇合適的HTTP訊息轉換器即可。
怎麼選擇呢?當然是透過 Spring MVC 為我們提供的註解,我們透過使用不同的註解來啟用不同的訊息轉換器。
我們重點牢牢把握住下面的這兩個註解,兩個類 ;
- 兩個註解:
@ResponseBody
@RequestBody
- 兩個類:
ResponseEntity
RequestEntity
4. Spring MVC中的 AJAX 請求
SpringMVC+Vue3+Thymeleaf+Axios傳送一個簡單的AJAX請求。
引入 Vue 和 Axios的js檔案:
匯入相關的 jar 依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.rainbowsea</groupId>
<artifactId>springmvc-008</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<!--springmvc依賴-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.1.4</version>
</dependency>
<!--logback依賴-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.3</version>
</dependency>
<!--servlet依賴-->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<!--thymeleaf和spring6整合的依賴-->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring6</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
<!-- 引入jackson依賴,可以將java物件轉換為json格式字串-->
<!-- 專門負責將Java物件轉換成JSON格式字串的元件,
當然,它也可以將JSON格式的字串轉換成Java物件-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
</dependencies>
</project>
web.xml 檔案的相關配置資訊內容:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<!-- 字元編碼過濾器-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<!-- 除了 jsp 頁面其他的都走這個-->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 新增一個過濾器,這個過濾器是springmvc提前寫好的,直接用就行了,這個過濾器可以幫助你將請求
POST轉換成PUT請求/DELETE請求-->
<!-- 同時注意:該過濾器一定要在字元編碼過濾器後面配置,不然,先設定的話,可能會出現獲取到的請求資料是亂碼-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<!-- 表示任意的 請求-->
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
相關 springmvc.xml 檔案配置資訊的編寫:
其中重點是:靜態資源處理、開啟註解驅動、檢視控制器對映等相關配置。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 元件掃描-->
<context:component-scan
base-package="com.rainbowsea.springmvc.controller,com.rainbowsea.springmvc.service"></context:component-scan>
<!--檢視解析器-->
<bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver">
<property name="characterEncoding" value="UTF-8"/>
<property name="order" value="1"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring6.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/thymeleaf/"/>
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML"/>
<property name="characterEncoding" value="UTF-8"/>
</bean>
</property>
</bean>
</property>
</bean>
<!-- 檢視控制器對映-->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
<!-- 開啟註解驅動-->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 靜態資源處理-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
</beans>
Vue3 + Thymeleaf + Axios 傳送 AJAX 請求:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首頁</title>
<script th:src="@{/static/js/vue3.4.21.js}"></script>
<script th:src="@{/static/js/axios.min.js}"></script>
</head>
<body>
<h1>使用 Vue3 + axios + Thymeleaf + SpringMVC 傳送 AJAX 請求</h1>
<hr>
<div id="app">
<h1>{{message}}</h1>
<button @click="getMessage">獲取訊息</button>
</div>
<script th:inline="javascript">
Vue.createApp({
data() {
return {
message: ''
}
},
methods: {
//非同步方法(ajax請求多數情況下都是非同步請求)
async getMessage() {
try {
// 傳送 ajax請求
// await axios.get('/springmvc/ajax')
//動態獲取 應用的根/springmvc/
const response = await axios.get([[@{/}]] + 'ajax')
// 將返回的資料交給 message
this.message = response.data
}catch
(e)
{
console.error(e)
}
}
}
}).mount("#app")
</script>
</body>
</html>
重點來了,Controller 怎麼寫呢?
之前我們都是傳統的請求,Controller 返回一個 邏輯檢視名 。然後交給 檢視解析器 —>進行解析,最後跳轉頁面。而 AJAX 請求是不需要跳轉頁面的,因為 AJAX 是頁面區域性重新整理,以前我們在 Servlet 中使用
response.getWriter( ).print("message")
的方式響應。在 Spring MVC 中怎麼辦呢?當然,我們在 Spring MVC 中也可以使用 Servelt 原生API 來完成整個功能,程式碼如下:
或者這樣也行:不需要有返回值
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.io.IOException;
import java.io.PrintWriter;
@Controller // 交給 Spring IOC 容器管理
public class AJAXController {
@RequestMapping(value = "/ajax",method = RequestMethod.GET)
public void ajax(HttpServletResponse response) throws IOException {
PrintWriter writer = response.getWriter();
writer.print("hell ajax,my name is Spring MVC");
}
}
啟動伺服器測試:http://localhost:8080/springmvc/
注意:如果採用這種方式響應,則和 springmvc.xml 檔案中配置的檢視解析器沒有關係,不走檢視解析器了。
難道我們以後 AJAX 請求 要使用上面這種原生Servlet API嗎?
不需要,我們可以使用 SpringMVC 中提供的 HttpMessageConverter 訊息轉換器。
我們要向前端響應一個字串 "hell ajax,my name is Spring MVC" ,這個 "hell ajax,my name is Spring MVC" 就是響應協議中的響應體。
我們可以使用 @ResponseBody註解
來啟用對應的訊息轉換器。而這種訊息轉換器只負責將Controller返回的資訊以響應體的形式寫入響應協議。
5. @ResponseBody 將伺服器端的 return 返回值轉化為“字串(JSON格式的字串)”再返回給客戶端
上面的 AJAX 案例,Controller的程式碼可以修改為:
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
import java.io.PrintWriter;
@Controller // 交給 Spring IOC 容器管理
public class AJAXController {
@RequestMapping(value = "/ajax", method = RequestMethod.GET)
@ResponseBody // 由於你使用了 @ResponseBody 註解
public String ajax() {
// 當前處理器方法上新增了 @ResponseBoay 註解,
// 那麼這個方法的返回值不再是邏輯檢視名稱了
// 而是作為響應協議的響應體進行響應。
return "hell ajax,my name is Spring MVC";
}
最核心需要理解的位置是:
return "hell ajax,my name is Spring MVC";
這裡的 "hell ajax,my name is Spring MVC" 不是邏輯檢視名稱了,而是作為響應體的內容進行響應。直接輸出到瀏覽器客戶端。
以上程式中使用的訊息轉換器是:
StringHttpMessageConverter
,為什麼會啟用這個訊息轉換器呢?因為你新增了@ResponseBody
這個註解了。
啟動伺服器測試:http://localhost:8080/springmvc/
通常 AJAX 請求需要伺服器給返回一段JSON格式的字串,可以返回JSON格式的字串嗎?
這是完全可以的,此時底層使用的訊息轉換器還是:StringHttpMessageConverter
當然可以,程式碼如下:
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
import java.io.PrintWriter;
@Controller // 交給 Spring IOC 容器管理
public class AJAXController {
@RequestMapping(value = "/ajax", method = RequestMethod.GET)
@ResponseBody // 由於你使用了 @ResponseBody 註解
public String ajax() {
// 當前處理器方法上新增了 @ResponseBoay 註解,
// 那麼這個方法的返回值不再是邏輯檢視名稱了
// 而是作為響應協議的響應體進行響應。
// JSON 格式的字串,然後響應到瀏覽器
return "{\"username\":\"zhangsan\",\"password\":\"1234\"}";
//return "hell ajax,my name is Spring MVC";
}
}
啟動伺服器測試:http://localhost:8080/springmvc/
這是完全可以的,此時底層使用的訊息轉換器還是:StringHttpMessageConverter
那如果在程式中是一個POJO物件,怎麼將POJO物件 以 JSON格式 的字串響應給瀏覽器呢 ?兩種方式:
第一種方式:自己寫程式碼 將POJO物件 轉換成JSON格式的字串(如上面所示 return "{"username":"zhangsan","password":"1234"}"; ),用上面的方式直接 return即可。
第二種方式:啟用
MappingJackson2HttpMessageConverter
訊息轉換器。
第二種方式:啟用MappingJackson2HttpMessageConverter
訊息轉換器。
啟用 MappingJackson2HttpMessageConverter 訊息轉換器的步驟如下:
第一步: 引入 jackson
依賴,可以將 java物件
轉換為 json格式字串
<!-- 引入jackson依賴,可以將java物件轉換為json格式字串-->
<!-- 專門負責將Java物件轉換成JSON格式字串的元件,
當然,它也可以將JSON格式的字串轉換成Java物件-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
第二步: 開啟註解驅動
這一步非常關鍵,開啟註解驅動後,在 HandlerAdapter 中會自動裝配一個訊息轉換器:MappingJackson2HttpMessageConverter
<mvc:annotation-driven/>
第三步: 我們想將以 POJO物件轉換為 JOSN 格式的字串,返回給客戶端,我們需要建立一個 POJO物件。
package com.rainbowsea.springmvc.pojo;
public class User {
private Long id;
private String name;
private String password;
public User() {
}
public User(Long id, String name, String password) {
this.id = id;
this.name = name;
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
第四步: 控制器方法使用 @ResponseBody 註解標註(非常重要),控制器方法返回這個POJO物件
import com.rainbowsea.springmvc.pojo.User;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
import java.io.PrintWriter;
@Controller // 交給 Spring IOC 容器管理
public class AJAXController {
@RequestMapping(value = "/ajax", method = RequestMethod.GET)
@ResponseBody // 由於你使用了 @ResponseBody 註解
public User ajax() {
// 當前處理器方法上新增了 @ResponseBoay 註解,
// 那麼這個方法的返回值不再是邏輯檢視名稱了
// 而是作為響應協議的響應體進行響應。
// 將 POJO物件轉換為 JSON格式的字串,然後響應到瀏覽器端
User user = new User(111L, "李華", "123");
return user;
// JSON 格式的字串,然後響應到瀏覽器
//return "{\"username\":\"zhangsan\",\"password\":\"1234\"}";
//return "hell ajax,my name is Spring MVC";
}
}
啟動伺服器測試:http://localhost:8080/springmvc/
以上程式碼底層啟動的就是:
MappingJackson2HttpMessageConverter 訊息轉換器。
它的功能很強大,可以將 POJO物件轉換成 JSON格式的字串,響應給前端。
其實這個訊息轉換器
MappingJackson2HttpMessageConverter
本質上只是比:StringHttpMessageConverter
稍微多了一個 JSON 字串的轉換,其他的還是一樣的。
6. 補充:@RestController = (@Controller + @ResponseBody )
因為我們現代的開發方式都是基於 AJAX 方式的,因此 @ResponseBody註解非常重要,很常用。 為了方便,Spring MVC中提供了一個註解 @RestController。這一個註解代表了:@Controller + @ResponseBody。 @RestController標註在類上即可。
被它標註的@RestController中所有的方法上都會自動標註 @ResponseBody
import com.rainbowsea.springmvc.pojo.User;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.io.PrintWriter;
@RestController // @Controller + @ResponseBody
public class AJAXController {
@RequestMapping(value = "/ajax", method = RequestMethod.GET)
public User ajax() {
// 當前處理器方法上新增了 @ResponseBoay 註解,
// 那麼這個方法的返回值不再是邏輯檢視名稱了
// 而是作為響應協議的響應體進行響應。
// 將 POJO物件轉換為 JSON格式的字串,然後響應到瀏覽器端
User user = new User(111L, "李華", "123");
return user;
}
}
7. @RequestBody 將前端的請求體的資訊轉換Java程式中的 POJO物件
該註解只能使用在處理器方法的形參上,
這個註解的作用是直接將請求體傳遞給Java程式,在Java程式中可以直接使用一個String 型別的變數接收這個請求體的內容。
底層使用的HTTP訊息轉換器是:FormHttpMessageConvertor
沒有保持一致的話,會賦值失敗。
在沒有使用 @RequestBody
這個註解的時候:
當請求體提交的資料是:
username=admin&password=123
那麼 Spring MVC會自動使用 FormHttpMessageConverter
訊息轉換器,將請求體轉換成 對應的 POJO物件,這裡是 user物件。
package com.rainbowsea.springmvc.controller;
import com.rainbowsea.springmvc.pojo.User;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.net.URI;
@Controller // 交給 Spring IOC 容器管理
public class RequestBodyController {
@RequestMapping(value = "/save", method = RequestMethod.POST)
public String saveUser( User user) {
// @RequestBody 將 將請求體轉換成user物件。在方法上使用
System.out.println(user);
// 不是邏輯檢視,是普通字串,因為前端傳送的請求是 AJAX 請求
return "ok";
}
}
當使用這個註解的時候:這個註解只能出現在方法的引數上。
import com.rainbowsea.springmvc.bean.User;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.net.URI;
@Controller // 交給 Spring IOC 容器管理
public class RequestBodyController {
@RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(@RequestBody String requestBodyStr) {
// @RequestBody 將 將請求體轉換成user物件。在方法上使用
System.out.println("請求體:" + requestBodyStr);
return "ok";
}
}
Spring MVC仍然會使用 FormHttpMessageConverter
訊息轉換器,將請求體直接以字串形式傳遞給 requestBodyStr 變數。
7.1 MappingJackson2HttpMessageConverter 將前端提交的 JSON 格式的字串,轉換為 Java程式中的POJO物件
如果在請求體中提交的是一個 JSON
格式的字串,這個 JSON 字串傳遞給 Spring MVC 之後,能不能將 JSON 字串轉換成 POJO 物件呢?
答案是:可以的
此時必須使用
@RequetBody
註解來完成,並且底層使用的訊息轉換器是:MappingJackson2HttpMessageConverter
。實現步驟如下:
- 第一步:引入 jackson 依賴
- 第二步:開啟註解驅動
- 第三步:建立POJO類,將POJO類作為控制器方法的引數,並使用 @RequestBody 註解標註該引數。
import com.rainbowsea.springmvc.pojo.User;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.net.URI;
@Controller // 交給 Spring IOC 容器管理
public class RequestBodyController {
@RequestMapping(value = "/save2", method = RequestMethod.POST)
public String saveUser(@RequestBody User user) {
// @RequestBody 將 將請求體轉換成user物件。在方法上使用
System.out.println(user);
System.out.println(user.getName());
System.out.println(user.getPassword());
// 不是邏輯檢視,是普通字串,因為前端傳送的請求是 AJAX 請求
return "ok";
}
}
第四步:在前端 請求體中提交 json格式 的資料。
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首頁</title>
<script th:src="@{/static/js/vue3.4.21.js}"></script>
<script th:src="@{/static/js/axios.min.js}"></script>
</head>
<body>
<h1>使用 Vue3 + axios + Thymeleaf + SpringMVC 傳送 AJAX 請求</h1>
<hr>
<div id="app">
<h1>{{message}}</h1>
<button @click="getMessage">獲取訊息</button>
</div>
<script th:inline="javascript">
// 傳送 ajax post 請求,並且在請求體當中提交json資料
// 注意:name ,password 要於對應將 json 轉換為 Bean物件上的屬性名一致
let jsonObj = {"name": "李華", "password": "123"}
Vue.createApp({
data() {
return {
message: ''
}
},
methods: {
//非同步方法(ajax請求多數情況下都是非同步請求)
async getMessage() {
console.log("sendjson")
try {
// 傳送 ajax請求
// await axios.get('/springmvc/ajax')
//動態獲取 應用的根/springmvc/
const response = await axios.post([[@{/}]] + 'save2',JSON.stringify(jsonObj),{
headers
:
{
// 請求體的狀態資訊
"Content-Type"
:
"application/json"
}
})
// 將返回的資料交給 message
this.message = response.data
} catch
(e) {
console.error(e)
}
}
}
}).mount("#app")
</script>
</body>
</html>
測試結果:
8. RequestEntity 類
RequestEntity 不是一個註解,是一個普通的類,這個類的例項封裝了整個請求協議:包括請求行,請求頭,請求體所有資訊。
該 RequestEntity 類出現在控制器方法的引數上。
使用測試:如下是對應的 html 頁面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首頁</title>
<script th:src="@{/static/js/vue3.4.21.js}"></script>
<script th:src="@{/static/js/axios.min.js}"></script>
</head>
<body>
<h1>使用 Vue3 + axios + Thymeleaf + SpringMVC 傳送 AJAX 請求</h1>
<hr>
<div id="app">
<h1>{{message}}</h1>
<button @click="getMessage">獲取訊息</button>
</div>
<script th:inline="javascript">
// 傳送 ajax post 請求,並且在請求體當中提交json資料
// 注意:name ,password 要於對應將 json 轉換為 Bean物件上的屬性名一致
let jsonObj = {"name": "李華", "password": "123"}
Vue.createApp({
data() {
return {
message: ''
}
},
methods: {
//非同步方法(ajax請求多數情況下都是非同步請求)
async getMessage() {
console.log("sendjson")
try {
// 傳送 ajax請求
// await axios.get('/springmvc/ajax')
//動態獲取 應用的根/springmvc/
const response = await axios.post([[@{/}]] + 'save2',JSON.stringify(jsonObj),{
headers
:
{
// 請求體的狀態資訊
"Content-Type"
:
"application/json"
}
})
// 將返回的資料交給 message
this.message = response.data
} catch
(e) {
console.error(e)
}
}
}
}).mount("#app")
</script>
</body>
</html>
package com.rainbowsea.springmvc.controller;
import com.rainbowsea.springmvc.pojo.User;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.net.URI;
@Controller // 交給 Spring IOC 容器管理
public class RequestBodyController {
@RequestMapping(value = "/save2", method = RequestMethod.POST)
public String saveUser(RequestEntity<User> requestEntity) {
// 獲取請求方法
HttpMethod method = requestEntity.getMethod();
System.out.println(method);
// 獲取請求URL
URI url = requestEntity.getUrl();
System.out.println(url);
// 獲取請求頭
HttpHeaders headers = requestEntity.getHeaders();
System.out.println(headers);
// 獲取請求頭中的內容型別
MediaType contentType = headers.getContentType();
System.out.println(contentType);
// 獲取請求體:
User user = requestEntity.getBody();
System.out.println(user);
return "ok";
}
}
測試結果:
9. ResponseEntity 類
ResponseEntity 不是註解,而是一個類。使用該類的例項可以封裝響應協議,包括:狀態行,響應頭,響應體。 也就是說:如果你想定製屬於自己的響應協議,可以使用該類。
舉例:這裡假如我們有這麼一個需求:
前端提交一個 id,後端根據 id 進行查詢,如果返回 null,請在前端顯示 404 錯誤,如果返回不是 null,則輸出返回 User 物件。
前端頁面設定:
後端處理:
首先編寫一個 Service 進行一個查詢處理,這裡我們就簡單判斷一下,就不連線資料庫了。
package com.rainbowsea.springmvc.service;
import com.rainbowsea.springmvc.pojo.User;
import org.springframework.stereotype.Service;
// 注意使用了註解,要用上元件掃描上
@Service
public class UserService {
public User getById(Long id) {
if(id == 1) {
return new User(11L,"張三","123");
}
return null;
}
}
最後是對應 Controller 控制器的編寫
package com.rainbowsea.springmvc.controller;
import com.rainbowsea.springmvc.pojo.User;
import com.rainbowsea.springmvc.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class UserController {
@Autowired // Spring 自動賦值,管理
private UserService userService;
@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
public ResponseEntity<User> getById(@PathVariable("id") Long id) {
User user = userService.getById(id);
if(user == null) {
// HttpStatus.NOT_FOUND 找不到錯誤 HTTP ERROR 404
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
} else {
return ResponseEntity.ok(user);
}
}
}
測試:當使用者存在時
測試:當使用者不存在時
10. 總結:
- HTTP 協議包括
請求協議
和響應協議
。- @ResponseBody 將伺服器端的 return 返回值轉化為“字串(JSON格式的字串)”再返回給客戶端。
- @ResponseBody 將POJO物件 以 JSON格式 的字串響應給瀏覽器
- 第一種方式:自己寫程式碼 將POJO物件 轉換成JSON格式的字串(如上面所示 return "{"username":"zhangsan","password":"1234"}"; ),用上面的方式直接 return即可。
- 第二種方式:啟用
MappingJackson2HttpMessageConverter
訊息轉換器。- 需要注意的時需要新增:涉及到 JSON格式的轉換,都需要匯入相關的jar包,以及開啟註解驅動。
- @RestController = (@Controller + @ResponseBody ), 被它標註的@RestController中所有的方法上都會自動標註 @ResponseBody
- @RequestBody 將前端的請求體的資訊轉換Java程式中的 POJO物件,該註解只能使用在處理器方法的形參上,還可以將 前端的請求體直接以字串形式傳遞給 requestBodyStr 變數。
@RequetBody
註解將前端提交的 JSON 格式的字串,轉換為 Java程式中的POJO物件,涉及到 JSON格式的轉換,都需要匯入相關的jar包,以及開啟註解驅動。- RequestEntity 類是一個普通的類,這個類的例項封裝了整個請求協議:包括請求行,請求頭,請求體所有資訊。 該 RequestEntity 類出現在控制器方法的引數上。
- ResponseEntity 是一個類。使用該類的例項可以封裝響應協議,包括:狀態行,響應頭,響應體。 也就是說:如果你想定製屬於自己的響應協議,可以使用該類。
- 無論是那個,只要涉及到 JSON格式的轉換,都需要匯入相關的jar包,以及開啟註解驅動。
11. 最後:
“在這個最後的篇章中,我要表達我對每一位讀者的感激之情。你們的關注和回覆是我創作的動力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會將你們的鼓勵留在心底,繼續在其他的領域奮鬥。感謝你們,我們總會在某個時刻再次相遇。”