ToB企服应用市场:ToB评测及商务社交产业平台

标题: Spring MVC 中 HttpMessageConverter 转换器 [打印本页]

作者: 十念    时间: 2024-7-13 17:46
标题: Spring MVC 中 HttpMessageConverter 转换器
1. Spring MVC 中 HttpMessageConverter 转换器

@
目录

2. 补充:什么是 HTTP 消息

HTTP 消息着实就是 HTTP 协议。HTTP 协议包罗 请求协议 和 响应协议。
以下是一份HTTP POST请求协议:
  1. POST /springmvc/user/login HTTP/1.1                                                                                                                                                                                                                                --请求行
  2. Content-Type: application/x-www-form-urlencoded                                                                                                                                                                                --请求头
  3. Content-Length: 32
  4. Host: www.example.com
  5. User-Agent: Mozilla/5.0
  6. Connection: Keep-Alive
  7. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  8.                                                                                           --空白行
  9. username=admin&password=1234                                                                                                                                                                                                                                                        --请求体
复制代码
以下是一份HTTP GET请求协议:
  1. GET /springmvc/user/del?id=1&name=zhangsan HTTP/1.1                                                                                                                                                                --请求行
  2. Host: www.example.com                                                                                                                                                                                                                                                                                        --请求头
  3. User-Agent: Mozilla/5.0
  4. Connection: Keep-Alive
  5. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
复制代码
以下是一份HTTP响应协议:
  1. HTTP/1.1 200 OK                                                                                                                                                                                                                                                                                                        --状态行
  2. Date: Thu, 01 Jul 2021 06:35:45 GMT                                                                                                                                                                                                                        --响应头
  3. Content-Type: text/plain; charset=utf-8
  4. Content-Length: 12
  5. Connection: keep-alive
  6. Server: Apache/2.4.43 (Win64) OpenSSL/1.1.1g
  7.                                                                                         --空白行
  8. <!DOCTYPE html>                                                                                                                                                                                                                                                                                                        --响应体
  9. <html>
  10.   <head>
  11.     <title>hello</title>
  12.   </head>
  13.   <body>
  14.     <h1>Hello World!</h1>
  15.   </body>
  16. </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 依赖
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5.     <modelVersion>4.0.0</modelVersion>
  6.     <groupId>com.rainbowsea</groupId>
  7.     <artifactId>springmvc-008</artifactId>
  8.     <version>1.0-SNAPSHOT</version>
  9.     <packaging>war</packaging>
  10.     <properties>
  11.         <maven.compiler.source>17</maven.compiler.source>
  12.         <maven.compiler.target>17</maven.compiler.target>
  13.     </properties>
  14.     <dependencies>
  15.         
  16.         <dependency>
  17.             <groupId>org.springframework</groupId>
  18.             <artifactId>spring-webmvc</artifactId>
  19.             <version>6.1.4</version>
  20.         </dependency>
  21.         
  22.         <dependency>
  23.             <groupId>ch.qos.logback</groupId>
  24.             <artifactId>logback-classic</artifactId>
  25.             <version>1.5.3</version>
  26.         </dependency>
  27.         
  28.         <dependency>
  29.             <groupId>jakarta.servlet</groupId>
  30.             <artifactId>jakarta.servlet-api</artifactId>
  31.             <version>6.0.0</version>
  32.             <scope>provided</scope>
  33.         </dependency>
  34.         
  35.         <dependency>
  36.             <groupId>org.thymeleaf</groupId>
  37.             <artifactId>thymeleaf-spring6</artifactId>
  38.             <version>3.1.2.RELEASE</version>
  39.         </dependency>
  40.         
  41.         
  42.         <dependency>
  43.             <groupId>com.fasterxml.jackson.core</groupId>
  44.             <artifactId>jackson-databind</artifactId>
  45.             <version>2.17.0</version>
  46.         </dependency>
  47.     </dependencies>
  48. </project>
复制代码
web.xml 文件的相关配置信息内容:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.          xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
  5.          version="5.0">
  6.    
  7.     <filter>
  8.         <filter-name>CharacterEncodingFilter</filter-name>
  9.         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  10.         <init-param>
  11.             <param-name>encoding</param-name>
  12.             <param-value>UTF-8</param-value>
  13.         </init-param>
  14.         <init-param>
  15.             <param-name>forceRequestEncoding</param-name>
  16.             <param-value>true</param-value>
  17.         </init-param>
  18.         <init-param>
  19.             <param-name>forceResponseEncoding</param-name>
  20.             <param-value>true</param-value>
  21.         </init-param>
  22.     </filter>
  23.     <filter-mapping>
  24.         <filter-name>CharacterEncodingFilter</filter-name>
  25.         <url-pattern>/*</url-pattern>
  26.     </filter-mapping>
  27.    
  28.     <servlet>
  29.         <servlet-name>DispatcherServlet</servlet-name>
  30.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  31.         <init-param>
  32.             <param-name>contextConfigLocation</param-name>
  33.             <param-value>classpath:springmvc.xml</param-value>
  34.         </init-param>
  35.     </servlet>
  36.     <servlet-mapping>
  37.         <servlet-name>DispatcherServlet</servlet-name>
  38.         
  39.         <url-pattern>/</url-pattern>
  40.     </servlet-mapping>
  41.    
  42.    
  43.     <filter>
  44.         <filter-name>HiddenHttpMethodFilter</filter-name>
  45.         <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  46.     </filter>
  47.     <filter-mapping>
  48.         <filter-name>HiddenHttpMethodFilter</filter-name>
  49.         
  50.         <url-pattern>/*</url-pattern>
  51.     </filter-mapping>
  52. </web-app>
复制代码
相关 springmvc.xml 文件配置信息的编写:
其中重点是:静态资源处理、开启注解驱动、视图控制器映射等相关配置。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.        xmlns:context="http://www.springframework.org/schema/context"
  5.        xmlns:mvc="http://www.springframework.org/schema/mvc"
  6.        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">
  7.    
  8.     <context:component-scan
  9.             base-package="com.rainbowsea.springmvc.controller,com.rainbowsea.springmvc.service"></context:component-scan>
  10.    
  11.     <bean id="thymeleafViewResolver" >
  12.         <property name="characterEncoding" value="UTF-8"/>
  13.         <property name="order" value="1"/>
  14.         <property name="templateEngine">
  15.             <bean >
  16.                 <property name="templateResolver">
  17.                     <bean >
  18.                         <property name="prefix" value="/WEB-INF/thymeleaf/"/>
  19.                         <property name="suffix" value=".html"/>
  20.                         <property name="templateMode" value="HTML"/>
  21.                         <property name="characterEncoding" value="UTF-8"/>
  22.                     </bean>
  23.                 </property>
  24.             </bean>
  25.         </property>
  26.     </bean>
  27.    
  28.     <mvc:view-controller path="/" view-name="index"></mvc:view-controller>
  29.    
  30.     <mvc:annotation-driven></mvc:annotation-driven>
  31.    
  32.     <mvc:default-servlet-handler></mvc:default-servlet-handler>
  33. </beans>
复制代码
Vue3 + Thymeleaf + Axios 发送 AJAX 请求:
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>首页</title>
  6.    
  7.    
  8. </head>
  9. <body>
  10. <h1>使用 Vue3 + axios + Thymeleaf + SpringMVC 发送 AJAX 请求</h1>
  11. <hr>
  12.     <h1>{{message}}</h1>
  13.     <button @click="getMessage">获取消息</button>
  14. </body>
  15. </html>
复制代码
重点来了,Controller 怎么写呢?
之前我们都是传统的请求,Controller 返回一个 逻辑视图名 。然后交给 视图解析器 —>进行解析,最后跳转页面。而 AJAX 请求是不需要跳转页面的,因为 AJAX 是页面局部革新,以前我们在 Servlet 中使用 response.getWriter( ).print("message") 的方式响应。在 Spring MVC 中怎么办呢?固然,我们在 Spring MVC 中也可以使用 Servelt 原生API 来完成整个功能,代码如下:

或者这样也行:不需要有返回值
  1. import jakarta.servlet.http.HttpServletResponse;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.RequestMapping;
  4. import org.springframework.web.bind.annotation.RequestMethod;
  5. import java.io.IOException;
  6. import java.io.PrintWriter;
  7. @Controller  // 交给 Spring IOC 容器管理
  8. public class AJAXController {
  9.     @RequestMapping(value = "/ajax",method = RequestMethod.GET)
  10.     public void ajax(HttpServletResponse response) throws IOException {
  11.         PrintWriter writer = response.getWriter();
  12.         writer.print("hell ajax,my name is Spring MVC");
  13.     }
  14. }
复制代码
启动服务器测试: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的代码可以修改为:
  1. import jakarta.servlet.http.HttpServletResponse;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.RequestBody;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RequestMethod;
  6. import org.springframework.web.bind.annotation.ResponseBody;
  7. import java.io.IOException;
  8. import java.io.PrintWriter;
  9. @Controller  // 交给 Spring IOC 容器管理
  10. public class AJAXController {
  11.     @RequestMapping(value = "/ajax", method = RequestMethod.GET)
  12.     @ResponseBody   // 由于你使用了 @ResponseBody 注解
  13.     public String ajax() {
  14.         // 当前处理器方法上添加了 @ResponseBoay 注解,
  15.         // 那么这个方法的返回值不再是逻辑视图名称了
  16.         // 而是作为响应协议的响应体进行响应。
  17.         return "hell ajax,my name is Spring MVC";
  18.     }
复制代码
最核心需要明白的位置是: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
固然可以,代码如下:
  1. import jakarta.servlet.http.HttpServletResponse;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.RequestBody;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RequestMethod;
  6. import org.springframework.web.bind.annotation.ResponseBody;
  7. import java.io.IOException;
  8. import java.io.PrintWriter;
  9. @Controller  // 交给 Spring IOC 容器管理
  10. public class AJAXController {
  11.     @RequestMapping(value = "/ajax", method = RequestMethod.GET)
  12.     @ResponseBody   // 由于你使用了 @ResponseBody 注解
  13.     public String ajax() {
  14.         // 当前处理器方法上添加了 @ResponseBoay 注解,
  15.         // 那么这个方法的返回值不再是逻辑视图名称了
  16.         // 而是作为响应协议的响应体进行响应。
  17.         // JSON 格式的字符串,然后响应到浏览器
  18.         return "{"username":"zhangsan","password":"1234"}";
  19.         //return "hell ajax,my name is Spring MVC";
  20.     }
  21. }
复制代码
启动服务器测试:http://localhost:8080/springmvc/

这是完全可以的,此时底层使用的消息转换器还是:StringHttpMessageConverter
那如果在步伐中是一个POJO对象,怎么将POJO对象 以 JSON格式 的字符串响应给浏览器呢 ?两种方式:

第二种方式:启用MappingJackson2HttpMessageConverter消息转换器。
启用 MappingJackson2HttpMessageConverter 消息转换器的步骤如下:
第一步: 引入 jackson依赖,可以将 java对象  转换为 json格式字符串
  1.   
  2.         
  3.         <dependency>
  4.             <groupId>com.fasterxml.jackson.core</groupId>
  5.             <artifactId>jackson-databind</artifactId>
  6.             <version>2.17.0</version>
  7.         </dependency>
复制代码
第二步: 开启注解驱动
这一步非常关键,开启注解驱动后,在 HandlerAdapter 中会自动装配一个消息转换器:MappingJackson2HttpMessageConverter
  1. [/code][b]第三步:[/b] 我们想将以 POJO对象转换为 JOSN 格式的字符串,返回给客户端,我们需要创建一个 POJO对象。
  2. [align=center][img]https://img2024.cnblogs.com/blog/3084824/202407/3084824-20240713190805076-1306129463.png[/img][/align]
  3. [code]package com.rainbowsea.springmvc.pojo;
  4. public class User {
  5.     private Long id;
  6.     private String name;
  7.     private String password;
  8.     public User() {
  9.     }
  10.     public User(Long id, String name, String password) {
  11.         this.id = id;
  12.         this.name = name;
  13.         this.password = password;
  14.     }
  15.     @Override
  16.     public String toString() {
  17.         return "User{" +
  18.                 "id=" + id +
  19.                 ", name='" + name + '\'' +
  20.                 ", password='" + password + '\'' +
  21.                 '}';
  22.     }
  23.     public Long getId() {
  24.         return id;
  25.     }
  26.     public void setId(Long id) {
  27.         this.id = id;
  28.     }
  29.     public String getName() {
  30.         return name;
  31.     }
  32.     public void setName(String name) {
  33.         this.name = name;
  34.     }
  35.     public String getPassword() {
  36.         return password;
  37.     }
  38.     public void setPassword(String password) {
  39.         this.password = password;
  40.     }
  41. }
复制代码
第四步: 控制器方法使用 @ResponseBody 注解标注(非常紧张),控制器方法返回这个POJO对象
  1. import com.rainbowsea.springmvc.pojo.User;
  2. import jakarta.servlet.http.HttpServletResponse;
  3. import org.springframework.stereotype.Controller;
  4. import org.springframework.web.bind.annotation.RequestBody;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RequestMethod;
  7. import org.springframework.web.bind.annotation.ResponseBody;
  8. import java.io.IOException;
  9. import java.io.PrintWriter;
  10. @Controller  // 交给 Spring IOC 容器管理
  11. public class AJAXController {
  12.     @RequestMapping(value = "/ajax", method = RequestMethod.GET)
  13.     @ResponseBody   // 由于你使用了 @ResponseBody 注解
  14.     public User ajax() {
  15.         // 当前处理器方法上添加了 @ResponseBoay 注解,
  16.         // 那么这个方法的返回值不再是逻辑视图名称了
  17.         // 而是作为响应协议的响应体进行响应。
  18.         // 将 POJO对象转换为 JSON格式的字符串,然后响应到浏览器端
  19.         User user = new User(111L, "李华", "123");
  20.         return user;
  21.         // JSON 格式的字符串,然后响应到浏览器
  22.         //return "{"username":"zhangsan","password":"1234"}";
  23.         //return "hell ajax,my name is Spring MVC";
  24.     }
  25. }
复制代码
启动服务器测试:http://localhost:8080/springmvc/

以上代码底层启动的就是: MappingJackson2HttpMessageConverter 消息转换器。
它的功能很强大,可以将 POJO对象转换成 JSON格式的字符串,响应给前端。
着实这个消息转换器MappingJackson2HttpMessageConverter  本质上只是比: StringHttpMessageConverter 稍微多了一个 JSON 字符串的转换,其他的还是一样的。
6. 补充:@RestController = (@Controller  + @ResponseBody )


因为我们现代的开发方式都是基于 AJAX 方式的,因此 @ResponseBody注解非常紧张,很常用。  为了方便,Spring MVC中提供了一个注解 @RestController。这一个注解代表了:@Controller + @ResponseBody。  @RestController标注在类上即可。
被它标注的@RestController中所有的方法上都会自动标注 @ResponseBody
  1. import com.rainbowsea.springmvc.pojo.User;
  2. import jakarta.servlet.http.HttpServletResponse;
  3. import org.springframework.stereotype.Controller;
  4. import org.springframework.web.bind.annotation.RequestBody;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RequestMethod;
  7. import org.springframework.web.bind.annotation.ResponseBody;
  8. import org.springframework.web.bind.annotation.RestController;
  9. import java.io.IOException;
  10. import java.io.PrintWriter;
  11. @RestController  // @Controller + @ResponseBody
  12. public class AJAXController {
  13.     @RequestMapping(value = "/ajax", method = RequestMethod.GET)
  14.     public User ajax() {
  15.         // 当前处理器方法上添加了 @ResponseBoay 注解,
  16.         // 那么这个方法的返回值不再是逻辑视图名称了
  17.         // 而是作为响应协议的响应体进行响应。
  18.         // 将 POJO对象转换为 JSON格式的字符串,然后响应到浏览器端
  19.         User user = new User(111L, "李华", "123");
  20.         return user;
  21.     }
  22. }
复制代码

7. @RequestBody 将前端的请求体的信息转换Java步伐中的 POJO对象


该注解只能使用在处理器方法的形参上,
这个注解的作用是直接将请求体传递给Java步伐,在Java步伐中可以直接使用一个String 类型的变量接收这个请求体的内容。
底层使用的HTTP消息转换器是:FormHttpMessageConvertor

没有保持一致的话,会赋值失败。


在没有使用 @RequestBody  这个注解的时候:
当请求体提交的数据是:
  1. username=admin&password=123
复制代码
那么 Spring MVC会自动使用 FormHttpMessageConverter消息转换器,将请求体转换成 对应的 POJO对象,这里是 user对象。
  1. package com.rainbowsea.springmvc.controller;
  2. import com.rainbowsea.springmvc.pojo.User;
  3. import org.springframework.http.HttpHeaders;
  4. import org.springframework.http.HttpMethod;
  5. import org.springframework.http.MediaType;
  6. import org.springframework.http.RequestEntity;
  7. import org.springframework.stereotype.Controller;
  8. import org.springframework.web.bind.annotation.RequestBody;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestMethod;
  11. import java.net.URI;
  12. @Controller  // 交给 Spring IOC 容器管理
  13. public class RequestBodyController {
  14.     @RequestMapping(value = "/save", method = RequestMethod.POST)
  15.     public String saveUser( User user) {
  16.         // @RequestBody 将 将请求体转换成user对象。在方法上使用
  17.         System.out.println(user);
  18.         // 不是逻辑视图,是普通字符串,因为前端发送的请求是 AJAX 请求
  19.         return "ok";
  20.     }
  21. }
复制代码

当使用这个注解的时候:这个注解只能出现在方法的参数上。
  1. import com.rainbowsea.springmvc.bean.User;
  2. import org.springframework.http.HttpHeaders;
  3. import org.springframework.http.HttpMethod;
  4. import org.springframework.http.MediaType;
  5. import org.springframework.http.RequestEntity;
  6. import org.springframework.stereotype.Controller;
  7. import org.springframework.web.bind.annotation.RequestBody;
  8. import org.springframework.web.bind.annotation.RequestMapping;
  9. import org.springframework.web.bind.annotation.RequestMethod;
  10. import java.net.URI;
  11. @Controller  // 交给 Spring IOC 容器管理
  12. public class RequestBodyController {
  13.     @RequestMapping(value = "/save", method = RequestMethod.POST)
  14.     public String save(@RequestBody String requestBodyStr) {
  15.         // @RequestBody 将 将请求体转换成user对象。在方法上使用
  16.          System.out.println("请求体:" + requestBodyStr);
  17.         return "ok";
  18.     }
  19. }
复制代码

Spring MVC仍然会使用 FormHttpMessageConverter消息转换器,将请求体直接以字符串形式传递给 requestBodyStr 变量。
7.1 MappingJackson2HttpMessageConverter 将前端提交的 JSON 格式的字符串,转换为 Java步伐中的POJO对象

如果在请求体中提交的是一个 JSON 格式的字符串,这个 JSON 字符串传递给 Spring MVC 之后,能不能将 JSON 字符串转换成 POJO 对象呢?
答案是:可以的
此时必须使用 @RequetBody 注解来完成,并且底层使用的消息转换器是:MappingJackson2HttpMessageConverter 。实现步骤如下:


  1. import com.rainbowsea.springmvc.pojo.User;
  2. import org.springframework.http.HttpHeaders;
  3. import org.springframework.http.HttpMethod;
  4. import org.springframework.http.MediaType;
  5. import org.springframework.http.RequestEntity;
  6. import org.springframework.stereotype.Controller;
  7. import org.springframework.web.bind.annotation.RequestBody;
  8. import org.springframework.web.bind.annotation.RequestMapping;
  9. import org.springframework.web.bind.annotation.RequestMethod;
  10. import java.net.URI;
  11. @Controller  // 交给 Spring IOC 容器管理
  12. public class RequestBodyController {
  13.     @RequestMapping(value = "/save2", method = RequestMethod.POST)
  14.     public String saveUser(@RequestBody User user) {
  15.         // @RequestBody 将 将请求体转换成user对象。在方法上使用
  16.         System.out.println(user);
  17.         System.out.println(user.getName());
  18.         System.out.println(user.getPassword());
  19.         // 不是逻辑视图,是普通字符串,因为前端发送的请求是 AJAX 请求
  20.         return "ok";
  21.     }
  22. }
复制代码
第四步:在前端 请求体中提交 json格式 的数据。
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>首页</title>
  6.    
  7.    
  8. </head>
  9. <body>
  10. <h1>使用 Vue3 + axios + Thymeleaf + SpringMVC 发送 AJAX 请求</h1>
  11. <hr>
  12.     <h1>{{message}}</h1>
  13.     <button @click="getMessage">获取消息</button>
  14. </body>
  15. </html>
复制代码
测试结果:

8. RequestEntity 类

RequestEntity 不是一个注解,是一个平凡的类,这个类的实例封装了整个请求协议:包罗请求行,请求头,请求体所有信息。
该 RequestEntity 类出现在控制器方法的参数上。

使用测试:如下是对应的 html 页面
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>首页</title>
  6.    
  7.    
  8. </head>
  9. <body>
  10. <h1>使用 Vue3 + axios + Thymeleaf + SpringMVC 发送 AJAX 请求</h1>
  11. <hr>
  12.     <h1>{{message}}</h1>
  13.     <button @click="getMessage">获取消息</button>
  14. </body>
  15. </html>
复制代码
  1. package com.rainbowsea.springmvc.controller;
  2. import com.rainbowsea.springmvc.pojo.User;
  3. import org.springframework.http.HttpHeaders;
  4. import org.springframework.http.HttpMethod;
  5. import org.springframework.http.MediaType;
  6. import org.springframework.http.RequestEntity;
  7. import org.springframework.stereotype.Controller;
  8. import org.springframework.web.bind.annotation.RequestBody;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestMethod;
  11. import java.net.URI;
  12. @Controller  // 交给 Spring IOC 容器管理
  13. public class RequestBodyController {
  14.     @RequestMapping(value = "/save2", method = RequestMethod.POST)
  15.     public String saveUser(RequestEntity<User> requestEntity) {
  16.         // 获取请求方法
  17.         HttpMethod method = requestEntity.getMethod();
  18.         System.out.println(method);
  19.         // 获取请求URL
  20.         URI url = requestEntity.getUrl();
  21.         System.out.println(url);
  22.         // 获取请求头
  23.         HttpHeaders headers = requestEntity.getHeaders();
  24.         System.out.println(headers);
  25.         // 获取请求头中的内容类型
  26.         MediaType contentType = headers.getContentType();
  27.         System.out.println(contentType);
  28.         // 获取请求体:
  29.         User user = requestEntity.getBody();
  30.         System.out.println(user);
  31.         return "ok";
  32.     }
  33. }
复制代码
测试结果:

9. ResponseEntity 类


ResponseEntity 不是注解,而是一个类。使用该类的实例可以封装响应协议,包罗:状态行,响应头,响应体。 也就是说:如果你想定制属于自己的响应协议,可以使用该类。
举例:这里如果我们有这么一个需求:
前端提交一个 id,后端根据 id 进行查询,如果返回 null,请在前端显示 404 错误,如果返回不是 null,则输出返回 User 对象。
前端页面设置:

后端处理:
首先编写一个 Service 进行一个查询处理,这里我们就简单判断一下,就不毗连数据库了。
  1. package com.rainbowsea.springmvc.service;
  2. import com.rainbowsea.springmvc.pojo.User;
  3. import org.springframework.stereotype.Service;
  4. // 注意使用了注解,要用上组件扫描上
  5. @Service
  6. public class UserService {
  7.     public User getById(Long id) {
  8.         if(id == 1) {
  9.             return new User(11L,"张三","123");
  10.         }
  11.         return null;
  12.     }
  13. }
复制代码
最后是对应 Controller 控制器的编写

  1. package com.rainbowsea.springmvc.controller;
  2. import com.rainbowsea.springmvc.pojo.User;
  3. import com.rainbowsea.springmvc.service.UserService;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.http.HttpStatus;
  6. import org.springframework.http.ResponseEntity;
  7. import org.springframework.stereotype.Controller;
  8. import org.springframework.web.bind.annotation.PathVariable;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestMethod;
  11. @Controller
  12. public class UserController {
  13.     @Autowired  // Spring 自动赋值,管理
  14.     private UserService userService;
  15.     @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
  16.     public ResponseEntity<User> getById(@PathVariable("id") Long id) {
  17.         User user = userService.getById(id);
  18.         if(user == null) {
  19.             // HttpStatus.NOT_FOUND  找不到错误  HTTP ERROR 404
  20.             return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
  21.         } else {
  22.             return ResponseEntity.ok(user);
  23.         }
  24.     }
  25. }
复制代码
测试:当用户存在时

测试:当用户不存在时

10. 总结:

11. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和复兴是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继承在其他的领域奋斗。感谢你们,我们总会在某个时候再次相遇。”


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4