【SpringMVC】| 报文信息转换器HttpMessageConverter

目录

框架搭建

报文信息转换器HttpMessageConverter

1. @RequestBody注解

2. RequestEntity类型

3. @RequestBody注解(常用)

重点:SpringMVC处理json

重点:SpringMVC处理ajax

重点:@RestController注解

4. ResponseEntity(实现文件的上传下载)

文件下载

文件上传

图书推荐《Spring Cloud 微服务快速上手》


框架搭建

pom.xml

<?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>org.example</groupId><artifactId>springmvc-thymeleaf006</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><name>springmvc-thymeleaf006 Maven Webapp</name><!-- FIXME change it to the project's website --><url>http://www.example.com</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.5.RELEASE</version></dependency><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring5</artifactId><version>3.0.10.RELEASE</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.2.3</version></dependency></dependencies><build><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include><include>**/*.properties</include></includes><filtering>false</filtering></resource><resource><directory>src/main/resources</directory><includes><include>**/*.xml</include><include>**/*.properties</include></includes><filtering>false</filtering></resource></resources></build></project>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!--注册过滤器:解决post请求乱码问题--><filter><filter-name>encode</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><!--强制request使用字符集encoding--><init-param><param-name>forceRequestEncoding</param-name><param-value>true</param-value></init-param><!--强制response使用字符集encoding--><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param></filter><!--所有请求--><filter-mapping><filter-name>encode</filter-name><url-pattern>/*</url-pattern></filter-mapping><!--发送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><!--注册SpringMVC框架--><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--配置springMVC位置文件的位置和名称--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><!--将前端控制器DispatcherServlet的初始化时间提前到服务器启动时--><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>springmvc</servlet-name><!--指定拦截什么样的请求例如:http://localhost:8080/demo.action--><url-pattern>/</url-pattern></servlet-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.zl.controller"/><!--视图控制器,需要搭配注解驱动使用--><mvc:view-controller path="/" view-name="index"/><!--专门处理ajax请求,ajax请求不需要视图解析器InternalResourceViewResolver--><!--但是需要添加注解驱动,专门用来解析@ResponseBody注解的--><!--注入date类型时,需要使用@DateTimeFormat注解,也要搭配这个使用--><mvc:annotation-driven/><!--开放对静态资源的访问,需要搭配注解驱动使用--><mvc:default-servlet-handler/><!-- 配置Thymeleaf视图解析器 --><bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver"><property name="order" value="1"/><property name="characterEncoding" value="UTF-8"/><property name="templateEngine"><bean class="org.thymeleaf.spring5.SpringTemplateEngine"><property name="templateResolver"><bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver"><!-- 视图前缀 --><property name="prefix" value="/WEB-INF/templates/"/><!-- 视图后缀 --><property name="suffix" value=".html"/><property name="templateMode" value="HTML5"/><property name="characterEncoding" value="UTF-8"/></bean></property></bean></property></bean></beans>

报文信息转换器HttpMessageConverter

(1)HttpMessageConverter,报文信息转换器,将请求报文转换为Java对象或将Java对象转换为响应报文。

(2)HttpMessageConverter提供了两个注解和两个类型:@RequestBody、@ResponseBody、RequestEntity、ResponseEntity!

1. @RequestBody注解

@RequestBody可以获取请求体,需要在控制器方法设置一个形参使用@RequestBody进行标识,当前请求的请求体就会为当前注解所标识的形参赋值! 

回顾:请求报文有三个部分组成:请求头、请求空行、请求体;对于Get请求没有请求体,只有Post请求才有请求体。因为Get请求会把请求参数拼接到地址栏,而Post请求则是放到请求体当中!

form表单提交数据

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>首页</title>
</head>
<body>
<form th:action="@{/testRequestBody}" method="post">用户名:<input type="text" name="username"><br>密码:<input type="password" name="password"><br><input type="submit" value="测试@RequestBody注解">
</form></body>
</html>

controller获取到请求体

package com.zl.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class HttpMessageConverterController {@RequestMapping("/testRequestBody")public String testRequestBody(@RequestBody String requestBody){System.out.println("requestBody:"+requestBody);return "success";}
}

执行结果

注:如果没有使用@RequestBody注解拿到的就是一个null! 

2. RequestEntity类型

RequestEntity封装请求报文的一种类型,也是需要在控制器方法的形参中设置该类型的形参,当前请求的请求报文就会赋值给该形参,可以通过getHeaders()获取请求头信息,通过getBody()获取请求体信息。

注:@RequestBody注解只是获取请求体信息,而RequestEntity可以获取整个请求信息!

form表单提交数据

<form th:action="@{/testRequestEntity}" method="post">用户名:<input type="text" name="username"><br>密码:<input type="password" name="password"><br><input type="submit" value="测试RequestEntity"><br>
</form>

controller获取到请求体

    @RequestMapping("/testRequestEntity")public String testRequestEntity(RequestEntity<String> requestEntity){// 获取请求头System.out.println("requestHeader:"+requestEntity.getHeaders());// 获取请求体System.out.println("requestBody:"+requestEntity.getBody());return "success";}

执行结果

3. @RequestBody注解(常用)

@ResponseBody用于标识一个控制器方法上,可以将该方法的返回值直接作为响应报文的响应体响应到浏览器! 

回顾:以前使用原生的ServletAPI响应数据到浏览器

前端发出请求

<a th:href="@{/testServletAPI}">使用原生的ServletAPI响应数据到浏览器</a>

controller获取到请求,相应数据到浏览器

    @RequestMapping("/testServletAPI")public void testServletAPI(HttpServletResponse response) throws IOException {// 调用getWriter方法获取到一个流PrintWriter out = response.getWriter();// 响应到浏览器out.println("Hello,Response");}

执行结果

现在:使用@ResponseBody注解响应数据到浏览器

前端发出请求

<a th:href="@{/testResponseBody}">使用@RequestBody注解响应数据到浏览器</a>

controller获取到请求,相应数据到浏览器

注:如果没有使用@ResponseBody注解,此时返回的success就会被当做视图名称被前端控制器加上前缀和后缀进行进行页面的跳转。如果加上@ResponseBody注解,此时返回的值就不会当做视图名称,而是当前响应体!

    @RequestMapping("/testResponseBody")@ResponseBodypublic String testRequestBody(){return "success..........";}

执行结果

重点:SpringMVC处理json

浏览器是只能识别字符串的,那么假如我们返回的是一个Java对象呢?此时浏览器就无法识别报错!怎么解决?转换成Json格式的数据!

User对象

package com.zl.bean;import java.time.Period;public class User {private String name;private Integer age;private String sex;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public User() {}public User(String name, Integer age, String sex) {this.name = name;this.age = age;this.sex = sex;}
}

返回一个User对象

    @RequestMapping("/testResponseUser")@ResponseBodypublic User testResponseUser(){return new User("张三",18,"男");}

执行结果:无法响应Java对象

@ResponseBody处理json的步骤 

①导入jackson的依赖

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.12.1</version>
</dependency>

②在SpringMVC的核心配置文件中开启mvc的注解驱动

注解驱动<mvc:annotation-driven/>:专门用来解析@ResponseBody注解的;此时在HandlerAdaptor中会自动装配一个消息转换器:MappingJackson2HttpMessageConverter,可以将响应到浏览器的Java对象转换为Json格式的字符串。

 <mvc:annotation-driven/>

③在处理器方法上使用@ResponseBody注解进行标识;此时将Java对象直接作为控制器方法的返回值返回,就会自动转换为Json格式的字符串

    @RequestMapping("/testResponseUser")@ResponseBodypublic User testResponseUser(){return new User("张三",18,"男");}

执行结果:把Java对象转换成Json格式的字符串显示到浏览器上

注:Json实际上有两种格式,使用大括号{}就是Json对象、使用方括号[]就是Json数组!对于对象我们使用 点 的方式进行访问,对于数组我们通过遍历的方式进行访问。例如:Java对象、Map集合转化成Json都是对象的形式存在、List集合转换成Json是以数组的方式存在。

注:实际上只增加了一个jackson的依赖就可以了,因为注解驱动前面很多地方都用到,例如:视图控制器、处理静态资源,上来就配置上了;而@Response注解是我们一直要用的。

重点:SpringMVC处理ajax

使用Vue发送ajax请求,需要引入两个库:

发送Ajax请求

注:这里ajax发送请求的导入库的时候:<script></script>不能写成<script />

<div id="app"><a @click="textAxios" th:href="@{/textAxios}">SpringMVC发送ajax请求</a>
</div>
<!--导入库,不能直接斜杠结尾,必须使用</script>才可以-->
<script type="text/javascript" th:src="@{/static/js/vue.js}" ></script>
<script type="text/javascript" th:src="@{/static/js/axios.min.js}" ></script>
<!--编写-->
<script type="text/javascript">new Vue({// 绑定容器el:"#app",// 触发事件methods:{// 发送ajax请求textAxios:function(event){// ajax请求axios({method:"post",url:event.target.href,params:{username:"admin",password:"123"}}).then(function (response){ // 就相当于使用ajax的回调函数alert(response.data);});// 取消超链接的默认行为event.preventDefault();}}});
</script>

控制器方法

    @RequestMapping("/textAxios")@ResponseBodypublic String testAjax(String username,String password){System.out.println("username:"+username+",password:"+password);return username+","+password;}

执行结果:成功拿到ajax发送的数据,并且不会页面跳转

重点:@RestController注解

@RestController注解是springMVC提供的一个复合注解,标识在控制器的类上,就相当于为类添加了@Controller注解,并且为其中的每个方法添加了@ResponseBody注解。

4. ResponseEntity(实现文件的上传下载)

ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文 !

注:使用ResponseEntity实现下载文件的功能!

文件下载

前端发出请求

<!--文件下载-->
<a th:href="@{/testDown}">下载1.jpg</a>

后端处理

第一步:创建一个方法,方法的返回值就是ResponseEntity类型,方法的参数就是HttpSession对象。

第二步:根据session对象获取到上下文对象applocation对象,然后调用application对象的getRealPath方法,获取到在该项目中的文件的真实路径。

第三步:根据这个真实路径创建一个IO输入流去读取数据;并创建一个byte数组,参数是is.avaliavle()表示获取该文件的所有字节,这样就不要循环了;调用read方法进行读取,返回的是读取到字节的数量,将流读取到字节数组中去。

第四步:创建响应头信息HttpHeaders对象,并调用add方法设置下载的方式以及文件的名字

第五步:设置响应状态码。

第六步:创建ResponseEntity对象,参数有三个:响应体、响应头、状态码。

第七步:关闭IO流,返回ResponseEntity对象。

@Controller
public class FileUpAndDownController {@RequestMapping("/testDown")// 方法的返回值就是ResponseEntity类型public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {//获取ServletContext上下文对象ServletContext application = session.getServletContext();//获取服务器中文件的真实路径String realPath = application.getRealPath("/static/img/1.jpg");//创建输入流InputStream is = new FileInputStream(realPath);//创建字节数组byte[] bytes = new byte[is.available()];//将流读到字节数组中is.read(bytes);//创建HttpHeaders对象设置响应头信息MultiValueMap<String, String> headers = new HttpHeaders();//设置要下载方式以及下载文件的名字(固定的)headers.add("Content-Disposition", "attachment;filename=1.jpg");//设置响应状态码HttpStatus statusCode = HttpStatus.OK;//创建ResponseEntity对象(响应体、响应头、状态码)ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);//关闭输入流is.close();return responseEntity;}
}

执行结果

文件上传

(1)文件上传要求form表单的请求方式必须为post,并且添加属性enctype="multipart/form-data"。默认这个值等于enctype="application/x-www-form-urlencoded",表示key=value的方式传输;设置成enctype="multipart/form-data",此时就是以二进制的方式传输。

(2)SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息。

前端发出请求

<!--文件上传-->
<form th:action="@{/testUp}" method="post" enctype="multipart/form-data">头像:<input type="file" name="photo"><br><input type="submit" value="上传">
</form>

a>添加依赖

<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version>
</dependency>

b>在springmvc.xml的配置文件中添加配置

注:SpringMVC是根据id获取这个Bean的,并且这个id必须叫multipartResolver!实际上我们需要的是MultipartResolver对象,但它是一个接口,所以就使用了它的实现类CommonsMultipartResolver对象。

<!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>

c>控制器方法

注:把上传的对象封装到MultipartFile对象当中去!

第一步:通过前面的CommonsMultipartResolver把传过来的photo转换成MultipartFile对象。

第二步:调用getOriginalFilename获取上传的文件名,例如:1.jpg。

第三步:解决文件重名问题,首先通过截取,获得文件的后缀;然后调用UUID.randomUUID().toString()方法获取一个32位的UUID,与得到的后缀名拼接一起。

第四步:通过session对象获取到application对象,调用方法获取一个目录的路径;如果还要判断这个目录是否存在,如果不存在就创建。

第五步:拼接一个新的目录:目录路径+分隔符+文件名。

第六步:调用transferTo方法实现上传功能。

    @RequestMapping("/testUp")public String testUp(MultipartFile photo, HttpSession session) throws IOException {//获取上传的文件的文件名String fileName = photo.getOriginalFilename();//处理文件重名问题String hzName = fileName.substring(fileName.lastIndexOf("."));fileName = UUID.randomUUID().toString() + hzName;//获取服务器中photo目录的路径ServletContext application = session.getServletContext();String photoPath = application.getRealPath("photo"); // 设置上传的位置,就是webapp下的photo// 创建目录(没有就创建)File file = new File(photoPath);if(!file.exists()){file.mkdir();}// 真正的路径:目录+分隔符+文件名String finalPath = photoPath + File.separator + fileName;//实现上传功能photo.transferTo(new File(finalPath));return "success";}

执行结果

图书推荐《Spring Cloud 微服务快速上手》

参与方式:

本次送书 2 本! 
活动时间:截止到 2023-06-15 00:00:00。

抽奖方式:利用程序进行抽奖。

参与方式:关注博主(只限粉丝福利哦)、点赞、收藏,评论区随机抽取,最多三条评论!

其它图书详情了解:IT BOOK 多得 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis入门(4)-list

redis中list数据会按照插入顺序进行排序&#xff0c;其底层是一个无头结点的双向链表&#xff0c;因此表头和表尾的操作性能较高&#xff0c;但中间元素操作性能较差。 1.lpush key element [element ] 从表头插入元素 lpush nosql redis hbase lpush nosql mongdb2.lrange…

项目计划、进度与控制

思维导图 项目计划、进度与控制-思维导图 第一部分 项目管理概述 什么是项目 约瑟夫朱兰博士也说过&#xff0c;项目就是在已经确定好的时间内必须解决的问题 什么是项目管理 图1-1 项目管理就是工具、人和系统 image.png 组织是人的集合&#xff0c;过程是人在处理。如果人…

基于PaddleDetection fairmot目标跟踪 C++ 部署

1 源码下载 PaddleDetection 2 工程编译 参考&#xff1a;paddle 目标检测C部署流程 3 导出模型 python tools/export_model.py -c configs/mot/fairmot/fairmot_dla34_30e_576x320.yml --output_dir ./inference -o weightshttps://paddledet.bj.bcebos.com/models/mot/…

浅谈 Android Tombstone(墓碑日志)分析步骤 - 02

tomestone 日志&#xff1a; *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** Build fingerprint: qti/trinket/trinket:11/RKQ1.211119.001/37:user/test-keys Revision: 0 ABI: arm Timestamp: 2023-06-19 23:47:310800 pid: 742, tid: 32482, name: CAM_M…

联想小新Pro16怎么重装Win10系统?联想小新Pro16重装系统Win10教程

如果您是联想小新Pro16的用户&#xff0c;并且想要重装Win10系统&#xff0c;那么您来对地方了&#xff0c;无论是出于系统崩溃、性能下降还是个人需求改变的原因&#xff0c;重新安装操作系统可以帮助您恢复电脑的正常运行和提升使用体验。以下小编将为您分享联想小新Pro16重装…

10 月发布,Ubuntu 23.10 已升级到 Linux Kernel 6.3 内核

导读Canonical 于近日宣布&#xff0c;代号为 Mantic Minotaur 的 Ubuntu 23.10 发行版本已升级基于 Linux Kernel 6.3 内核。 Canonical宣布&#xff0c;代号为 Mantic Minotaur 的 Ubuntu 23.10 发行版本已升级基于 Linux Kernel 6.3 内核。 Ubuntu 23.10 于今年 4 月下旬进入…

ISP之图像降分辨率

1、图像缩放背景 图像的放大、缩小(简称缩放)是图像处理的一种处理方法。所谓图像缩放是指图像分辨率的改变&#xff0c;它在图像显示、传输、图像分析以及动画制作、电影合成、甚至医学图像处理中都有着相当广泛的应用。比如要在1024 X 768 分辨率的显示器上全屏显示800 X 60…

Docker安全

一、Docker 容器与虚拟机的区别 1、隔离与共享 • 虚拟机通过添加 Hypervisor 层&#xff0c;虚拟出网卡、内存、CPU 等虚拟硬件&#xff0c;再在其上建立虚拟机&#xff0c;每个虚拟机都有自己的系统内核 • Docker容器则是通过隔离的方式&#xff0c;将文件系统、进程、设…

使用RabbitMQ死信队列关闭未支付的订单

一、什么是RabbitMQ死信队列 RabbitMQ死信队列&#xff08;Dead-Letter Exchange&#xff0c;简称DLX&#xff09;是一种特殊类型的交换机&#xff0c;用于处理在队列中无法被消费的消息。当消息无法被消费时&#xff0c;它会被转发到死信队列中&#xff0c;以便进一步处理。 …

云原生——Docker容器化实战

❄️作者介绍&#xff1a;奇妙的大歪❄️ &#x1f380;个人名言&#xff1a;但行前路&#xff0c;不负韶华&#xff01;&#x1f380; &#x1f43d;个人简介&#xff1a;云计算网络运维专业人员&#x1f43d; 前言 "Docker"一词指代了多个概念&#xff0c;包括开源…

云端安全由繁到简,亚马逊云科技护航业务创新新局面

数字化愿景与现实存在的差距困扰着诸多企业&#xff0c;但造成这种差距的一个重要因素却一直被很多管理者所忽视&#xff0c;那就是企业未能建立应有的数字安全与合规体系。应用迭代的速度加快、数据快速膨胀、企业云原生道路上遭遇的种种困境&#xff0c;与数字安全部门有限的…

大学智慧课堂系统整理

目录 一、题目类型选择器(非组件库) 1.1、效果展示 1.2、代码展示 二、题目类型选择器(Vant组件库) 2.1、效果展示 2.2、代码展示 一、题目类型选择器(非组件库) 使用vue2&#xff1a;在methods里区分单个点击和多个点击&#xff0c;在view视图区分判断题和选择题。 如下…