Spring MVC 中 HttpMessageConverter 转换器

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 。实现步骤如下:

  1. 第一步:引入 jackson 依赖

在这里插入图片描述

  1. 第二步:开启注解驱动

在这里插入图片描述

  1. 第三步:创建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. 总结:

  1. HTTP 协议包括 请求协议响应协议
  2. @ResponseBody 将服务器端的 return 返回值转化为“字符串(JSON格式的字符串)”再返回给客户端。
  3. @ResponseBody 将POJO对象 以 JSON格式 的字符串响应给浏览器
    1. 第一种方式:自己写代码 将POJO对象 转换成JSON格式的字符串(如上面所示 return “{“username”:“zhangsan”,“password”:“1234”}”; ),用上面的方式直接 return即可。
    2. 第二种方式:启用MappingJackson2HttpMessageConverter消息转换器。
    3. 需要注意的时需要添加:涉及到 JSON格式的转换,都需要导入相关的jar包,以及开启注解驱动。
  4. @RestController = (@Controller + @ResponseBody ), 被它标注的@RestController中所有的方法上都会自动标注 @ResponseBody
  5. @RequestBody 将前端的请求体的信息转换Java程序中的 POJO对象,该注解只能使用在处理器方法的形参上,还可以将 前端的请求体直接以字符串形式传递给 requestBodyStr 变量。
  6. @RequetBody 注解将前端提交的 JSON 格式的字符串,转换为 Java程序中的POJO对象,涉及到 JSON格式的转换,都需要导入相关的jar包,以及开启注解驱动。
  7. RequestEntity 类是一个普通的类,这个类的实例封装了整个请求协议:包括请求行,请求头,请求体所有信息。 该 RequestEntity 类出现在控制器方法的参数上。
  8. ResponseEntity 是一个类。使用该类的实例可以封装响应协议,包括:状态行,响应头,响应体。 也就是说:如果你想定制属于自己的响应协议,可以使用该类。
  9. 无论是那个,只要涉及到 JSON格式的转换,都需要导入相关的jar包,以及开启注解驱动。

11. 最后:

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

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/796838.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RIP路由协议概述

RIP【Routing Information Protocol】 RIP是为TCP/IP 环境中开发的第一个路由选择协议标准 RIP是一个【距离——矢量】路由选择协议 当路由器的更新周期为30s到来时&#xff0c;向邻居发送路由表 RIP以跳数作为唯一度量值 RIP工作原理 RIP路由协议向邻居发送整个路由表信息RI…

Linux 复现Docker NAT网络

Linux 复现Docker NAT网络 docker 网络的构成分为宿主机docker0网桥和为容器创建的veth 对构成。这个默认网络命名空间就是我们登陆后日常使用的命名空间 使用ifconfig命令查看到的就是默认网络命名空间&#xff0c;docker0就是网桥&#xff0c;容器会把docker0当成路由&…

JavaDS —— 单链表 与 LinkedList

顺序表和链表区别 ArrayList &#xff1a; 底层使用连续的空间&#xff0c;可以随机访问某下标的元素&#xff0c;时间复杂度为O&#xff08;1&#xff09; 但是在插入和删除操作的时候&#xff0c;需要将该位置的后序元素整体往前或者向后移动&#xff0c;时间复杂度为O&…

代码随想录二刷7.22|977.有序数组的平方

暴力解法&#xff1a; ——如果想暴力解决这个问题的话&#xff0c;可以像题目那样&#xff0c;先将每一个元素平方&#xff0c;然后再排序 双指针&#xff1a; ——从题目中找到的信息&#xff1a;这是一个非递减顺序的整数数组&#xff0c;从例子中&#xff0c;可以容易看…

excel 百分位函数 学习

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、函数说明PERCENTILE 函数PERCENTILE.inc 函数PERCENTILE.exc 函数QUARTILE.EXC 函数 二、使用步骤总结 前言 excel 百分位函数 Excel提供了几个函数用于…

数据库MySQL下载安装

MySQL下载安装地址如下&#xff1a; MySQL :: Download MySQL Community Server 1、下载界面 2、点击下载 3、解压记住目录 4、配置my.ini文件 未完..

vector 介绍

1.简述vector 首先我们要大致弄明白vector是一个什么东西,其实vector就是之前我们学过的顺序表,这里直接使用就行了. 定义vector-------->vector<typename> arr 此时的这种定义vector可以理解成为一个数组,而typename可以是各种数据类型,比如string,int,double....…

QT实现自定义带有提示信息的透明环形进度条

1. 概述 做界面开发的童鞋可能都会遇到这样的需求&#xff0c;就是有一些界面点击了之后比较耗时的操作&#xff0c;需要界面给出一个环形进度条的进度反馈信息. 如何来实现这样的需求呢&#xff0c;话不多说&#xff0c;上效果 透明进度条 2. 代码实现 waitfeedbackprogressba…

3-2 多层感知机的从零开始实现

import torch from torch import nn from d2l import torch as d2lbatch_size 256 # 批量大小为256 train_iter, test_iter d2l.load_data_fashion_mnist(batch_size) # load进来训练集和测试集初始化模型参数 回想一下&#xff0c;Fashion-MNIST中的每个图像由 28 28 784…

一文了解5G新通话技术演进与业务模型

5G新通话简介 5G新通话&#xff0c;也被称为VoNR&#xff0c;是基于R16及后续协议产生的一种增强型语音通话业务。 它在IMS网络里新增数据通道&#xff08;Data Channel&#xff09;&#xff0c;承载通话时的文本、图片、涂鸦、菜单等信息。它能在传统话音业务基础上提供更多服…

红日靶场----(三)1.漏洞利用

上期已经信息收集阶段已经完成&#xff0c;接下来是漏洞利用。 靶场思路 通过信息收集得到两个吧靶场的思路 1、http://192.168.195.33/phpmyadmin/&#xff08;数据库的管理界面&#xff09; root/root 2、http://192.168.195.33/yxcms/index.php?radmin/index/login&am…

练习 6.7:⼈们 在为练习 6.1 编写的程序中,再创建两个表⽰⼈的字典,然后将这三个字典都存储在⼀个名为 people 的列表中。

练习 6.7&#xff1a;⼈们 在为练习 6.1 编写的程序中&#xff0c;再创建两个表⽰⼈的字典&#xff0c;然后将这三个字典都存储在⼀个名为 people 的列表中。 要求 遍历这个列表&#xff0c;将其中每个⼈的所有信息都打印出来。 代码 human {shuicc: {first_name: shui,la…

linux下安装cutecom串口助手;centos安装cutecom串口助手;rpm安装包安装cutecom串口助手

在支持apt-get的系统下安装 在终端命令行中输入&#xff1a; sudo apt-get install cutecom 安装好后输入 sudo cutecom 就可以了 关于如何使用&#xff0c;可以看这个https://www.cnblogs.com/xingboy/p/14388610.html 如果你的电脑不支持apt-get。 那我们就通过安装包…

druid(德鲁伊)数据线程池连接MySQL数据库

文章目录 1、druid连接MySQL2、编写JDBCUtils 工具类 1、druid连接MySQL 初学JDBC时&#xff0c;连接数据库是先建立连接&#xff0c;用完直接关闭。这就需要不断的创建和销毁连接&#xff0c;会消耗系统的资源。 借鉴线程池的思想&#xff0c;数据连接池就这么被设计出来了。…

【Unity2D 2022:NPC】制作任务系统

一、接受任务 1. 编辑NPC对话脚本&#xff1a; &#xff08;1&#xff09;创建静态布尔变量用来判断ruby是否接受到任务 public class NPCDialog : MonoBehaviour {// 创建全局变量用来判断ruby是否接到任务public static bool receiveTask false; } &#xff08;2&#xff…

git自动pull同步远程若干分支与本地若干分支

git自动pull同步远程若干分支与本地若干分支 假设远程代码仓库有100个分支&#xff0c;而本地只有10个本地分支与远程分支一一对应&#xff0c;现在要保持本地的这个10个分支与远程一致&#xff0c;最笨的方法是checkout到每个分支&#xff0c;然后一个一个的 git pull origin…

展望未来:在【PyCharm】中结合【机器学习】实现高效的图形化处理

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 引言一、PyCharm简介与配置1.1 PyCharm基础1.2 图形化库配置 二、机器学习项目中的数据可视化2.1 数据加载与预处理2.2 数据探索性可视化2.3 模型训练与结果可视化 三、PyCharm中的图形化调试四、高级…

【香橙派 Orange pi AIpro】| 开发板深入使用体验

目录 一. &#x1f981; 写在前面二. &#x1f981; 愉快的安装流程2.1 安装前准备2.2 流程准备2.2.1 烧录镜像2.2.2 开机2.2.3 连网2.2.4 SSH远程连接开发板 2.3 体验 AI 应用样例 三. &#x1f981; 写在最后 一. &#x1f981; 写在前面 大家好&#xff0c;我是狮子呀&…

【kubernetes】Helm包管理器基本概念与Chart实战

概念&#xff1a;基础架构与常用命令 三个重要概念&#xff1a; 1.chart 创建Kukernetes应用程序所必需的一组信息。 2.config 包含了可以合并到打包的chart中的配置信息&#xff0c;用于创建一个可发布的对象。 3.release 是一个与特走配置相结合的chart的运行实例。 常用命…

二叉搜索树大冒险:寻找-插入-删除

OK&#xff0c;看我们题目就可知道啦&#xff0c;今天要分享学习的一种数据结构就是二叉搜索树。 内容题目也说了三个大概的&#xff0c;分别是寻找、插入、删除。 讲这个之前呢&#xff0c;那么就先讲讲这个二叉搜索树是何方神圣呢&#xff1f; 二叉搜索树&#xff1a; 又…