day11-JSON处理和HttpMessageConverter<T>
JOSN处理和HttpMessageConverter
1.JSON处理-@ResponseBody
说明:在实际开发中,我们往往需要服务器返回的数据都是 JSON 格式。
SpringMVC 提供了 @ResponseBody 注解,用来标注 Controller 方法的返回的格式为 JSON,将 Java 对象或集合转为 JSON 格式的数据。
方法返回的对象通过适当的转换器转换为指定的格式之后,写入到 response 对象的 body 区,通常用来返回 JSON 数据或者是 XML 数据。
注意:在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,它的效果等同于通过 response对象输出指定格式的数据。
使用案例
下面是要完成的效果:请求目标方法,目标方法返回一个json格式的数据
(1)引入处理JSON需要的jar包,注意spring5.x 需要使用jackson-2.9.x.jar 的包。
(2)创建 json.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>json提交</title>
<!--引入jquery-->
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<!--使用jquery的ajax-->
<script type="text/javascript">
$(function () {
//给id=getJson的超链接绑定一个事件
$("#getJson").click(function () {
var href = this.href;
var args = {"time": new Date()};
$.get(
href,//请求url
args,//发送时间,防止浏览器缓存
function (data) {
console.log("data=", data)
},
"json"//指定返回的格式
)
return false;//超链接不跳转
})
})
</script>
</head>
<body>
<h1>请求一个json数据</h1>
<a href="<%=request.getContextPath()%>/json/dog" id="getJson">点击获取json数据</a>
</body>
</html>
(3)创建 Javabean 作为返回的数据
package com.li.web.json.entity;
/**
* @author 李
* @version 1.0
*/
public class Dog {
private String name;
private String address;
public Dog() {
}
public Dog(String name, String address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
(4)创建 JsonHandler 处理请求
package com.li.web.json;
import com.li.web.json.entity.Dog;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author 李
* @version 1.0
*/
@Controller
public class JsonHandler {
/**
* 1.目标方法的 @ResponseBody注解表示返回的数据是json格式
* 2.SpringMVC 底层根据目标方法@ResponseBody,返回指定格式
* 返回的格式根据http请求来处理
* 3.底层原理之前在实现SpringMVC底层机制时讲过,
* 这里原生的SpringMVC使用了转换器 HttpMessageConverter
* @return
*/
@RequestMapping(value = "/json/dog")
@ResponseBody
public Dog getJson(){
//返回对象
//SpringMVC 会根据你的设置,转成json格式数据返回
Dog dog = new Dog();
dog.setName("大黄狗");
dog.setAddress("小新的家");
return dog;
}
}
(5)启动tomcat,访问json.jsp页面。点击超链接,返回如下信息:
2.JSON处理-@RequestBody
和 @ResponseBody 注解相反,@RequestBody 注解是将客户端提交的 json数据,封装成 Javabean 对象。
注意:@RequestBody 用于修饰参数。
应用案例
在前端页面发出一个json数据,后端接收数据,并使用 @RequestBody 注解将 json 数据转成 Javabean 对象,然后使用 @ResponseBody 注解将该 Javabean 对象转回 json 数据,返回给前端。
(1)修改json.jsp,增加发送 json 数据代码
这里使用 ajax 请求的 contentType 指定发送格式为 json,发送请求时会被封装到请求头中。这样后端在接收时,根据 contentType 能知道数据是 json 格式的。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>json提交</title>
<!--引入jquery-->
<script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
<!--使用jquery的ajax-->
<script type="text/javascript">
$(function () {
//绑定按键点击事件,提交json数据
$("button[name='but1']").click(function () {
var url = "/springmvc/save2";
var username = $("#username").val();
var age = $("#age").val();
//将 username和 age封装成 json字符串
var args = {"username": username, "age": age};//json对象
//将json对象封装成json字符串
var jsonString = JSON.stringify(args);//json字符串
$.ajax({
url:url,
data:jsonString,
type:"POST",
success:function (data) {
console.log("返回的data=",data)
},
//指定发送数据的编码和格式
contentType:"application/json;charset=utf-8"
})
})
})
</script>
</head>
<body>
<h1>发出一个json数据</h1>
u:<input id="username" type="text"/><br/>
a:<input id="age" type="text"/><br/>
<button name="but1">添加用户</button>
</body>
</html>
(2)User.java
package com.li.web.json.entity;
/**
* @author 李
* @version 1.0
*/
public class User {
private String username;
private Integer age;
public User() {
}
public User(String username, Integer age) {
this.username = username;
this.age = age;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
}
(3)JsonHandler.java
package com.li.web.json;
import com.li.web.json.entity.User;
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.ResponseBody;
/**
* @author 李
* @version 1.0
*/
@Controller
public class JsonHandler {
/**
* 1.在形参指定了 @RequestBody 注解
* 2.SpringMVC 就会将提交的json字符串数据填充给指定的Javabean
* @param user 指定的Javabean对象
* @return 这里使用了 @ResponseBody 注解,因此返回的也是json
*/
@RequestMapping(value = "/save2")
@ResponseBody
public User save2(@RequestBody User user) {
//将前端传过来的数据以json的格式返回浏览器
System.out.println("user=" + user);
return user;
}
}
(4)启动tomcat,访问json.jsp,提交和返回的数据如下:
后台输出:
说明后端成功拿到了前端发送的 json 数据,并将其填充到了指定的Javabean对象中。然后又将 Javabean 对象转成了 json 格式的数据返回前端。
3.JSON处理-注意事项和细节
目标方法正常返回 Json 需要的数据,可以是一个对象,也可以是一个集合
@ResponseBody 注解也可以用于修饰于 Controller 上,这样会对 Controller 中所有方法生效
@ResponseBody 和 @Controller 可以直接写成一个注解 @RestController
4.HttpMessageConverter
- 基本说明
SpringMVC 处理 JSON 底层实现是依靠 HttpMessageConverter<T>
来进行转换的
- 工作机制简图
整个过程为:
请求报文发送到后端,HttpInputMessage 的实现子类会将请求报文封装起来,然后找到对应的转换器进行转换,然后封装成对应的 Java 对象给到目标方法。
目标方法返回,找到指定格式对应的消息转换器,消息转换器将返回的数据再进行转换,将转换后的数据封装到 HttpOutputMessage ,然后返回给客户端。
这里的 HttpMessageConverter(消息转换器),HttpInputMessage 和 HttpOutputMessage 都是接口,下面有很多实现子类,会根据请求/响应报文头来找到匹配子类。
- 处理JSON-底层实现(HttpMessageConverter< T>)
- 使用
HttpMessageConverter<T>
将请求信息转换并绑定到处理方法的入参中,或将响应结果转为对应类型的响应信息,Spring 提供了两种途径:- 使用
@RequestBody
/@ResponseBody
对目标方法或方法参数进行标注 - 使用
HttpEntity<T>
/ResponseEntity<T>
作为目标方法的入参或返回值
- 使用
- 当控制器处理方法使用到
@RequestBody / @ResponseBody
或HttpEntity<T> / ResponseEntity<T>
时,Spring 首先根据请求头或响应头的 Accept 属性选择匹配的 HttpMessageConverter,进而根据参数类型或泛型类型的过滤得到匹配的消息转换器 HttpMessageConverter,若找不到可用的消息转换器,将会报错。
debug源码
以处理JSON-@RequestBody的例子为案例:
(1)快捷键 ctrl+n 在 IDEA 中搜索 AbstractJackson2HttpMessageConverter 类,在该类的 readJavaType() 方法中打上断点,点击 debug
(2)浏览器访问 json.jsp 页面,填写数据并点击按钮
(3)后台光标跳转到断点处,此时方法参数 inputMessage 的数据如下,说明此时 http 请求的内容已经被封装到了给对象中。
方法参数 javaType 用于指定 inputMessage 的相应数据填充到什么样的 Java 类型中
(4)点击 step over,方法首先获取http请求数据指定的类型 contentType
(5)在获取了指定的数据类型后,将数据进行转换
(6)点击 step over:
(7)在目标方法中添加断点,点击 resume,可以看到光标跳转到断点处,此时目标方法就拿到了由json数据填充后的 Javabean对象
(8)在 AbstractJackson2HttpMessageConverter 类的 writeInternal() 方法中打上断点,点击 resume,光标跳转到如下位置:
由于我们在目标方法使用了 @ResponseBody 注解,因此返回的时候不再会进入视图处理器,而是通过消息转换器,将返回的 user 对象转换为指定的 json 格式数据。下图的 HttpOutputMessage 对象就是用于存放转换后的数据。
获取要转换的格式:
使用 selectObjectMapper 方法将对象转换为指定格式:
后面就是进行一些处理,然后将数据返回给客户端。
(9)然后浏览器获得指定格式的数据:
5.文件下载-ResponseEntity< T>
- 说明
在SpringMVC 中,通过返回 ResponseEntity<T>
的类型,可以实现文件的下载功能
使用案例
实现效果如下:在前端页面点击超链接,可以实现文件下载。
(1)修改json.jsp
(2)修改 JsonHandler.java,增加方法,用于响应下载文件的请求
day11-JSON处理和HttpMessageConverter<T>的更多相关文章
- 安卓里面JSON处理和JAVA SE里面的JSON包
今天编译安卓项目遇到这个问题 com.android.dex.DexException: Multiple dex files define的解决办法 大致意思就是引用了 相同的包 在JAVA SE里 ...
- IOS UI-键盘处理和UIToolbar
// // ViewController.m // IOS_0225-键盘处理和UIToolBar // // Created by ma c on 16/2/25. // Copyright © 2 ...
- C++复习8.异常处理和RTTI
C++异常处理和RTTI技术 20130930 1.异常处理的基本知识 C语言中是没有内置运行时错误处理机制,对于错误发生的时候使用的几种处理机制: 函数返回彼此协商后统一定义的状态编码来表示操作成功 ...
- JavaWeb:Cookie处理和Session跟踪
JavaWeb:Cookie处理和Session跟踪 Cookie处理 什么是Cookie Cookie 是存储在客户端计算机上的文本文件,保留了各种跟踪信息.因为HTTP协议是无状态的,即服务器不知 ...
- 学习笔记:CentOS7学习之二十五:shell中色彩处理和awk使用技巧
目录 学习笔记:CentOS7学习之二十五:shell中色彩处理和awk使用技巧 25.1 Shell中的色彩处理 25.2 awk基本应用 25.2.1 概念 25.2.2实例演示 25.3 awk ...
- C异常处理和C++异常处理的对比
每一种编译器实现异常处理的方式会有所不同,但是都是基于Windows的SEH异常处理.这里以MSC编译器为例. C异常处理 #include <Windows.h> int main(in ...
- 数据存储之json文件处理和csv文件处理
什么是json: JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式.它基于 ECMAScript (w3c制定的js规范)的一个子集,采用 ...
- 一.文件处理和json模块(容易混淆知识点即用法)
一.文件处理 注意点1: 打开文件包含两部分资源:操作系统级打开得文件+应用程序的变量. 在操作完毕一个文件时,必须把该文件的两部分资源一个不落的回收 如下: f.close() #回收操作系统级打开 ...
- python之异常处理和re模块补充
一.re模块的补充 1.从一个字符串中获取要匹配的内容 findall:返回一个列表 2.search ***** 验证用户输入内容 '^正则规则$':返回一个对象,用group()取值 3.matc ...
- Vuex、axios、跨域请求处理和import/export的注意问题
一.Vuex 1.介绍 vuex是一个专门为Vue.js设计的集中式状态管理架构. 对于状态,我们把它理解为在data中需要共享给其他组件使用的部分数据. Vuex和单纯的全局对象有以下不同: 1. ...
随机推荐
- ROSIntegration ROSIntegrationVision与虚幻引擎4(Unreal Engine 4)的配置
ROSIntegration ROSIntegrationVision与虚幻引擎4(Unreal Engine 4)的配置 操作系统:Ubuntu 18.04 虚幻引擎:4.26.2 目录 ROSIn ...
- 本地GoLand编辑与调试远端服务器上的代码
Goland是专为Go开发人员构建的跨平台IDE,功能非常强大,拥有强大的代码洞察力,帮助所有Go开发人员即时错误检测和修复建议,快速和安全的重构,一步撤销,智能代码完成,死代码检测和文档提示,让您创 ...
- OSI传输层TCP与UDP协议、应用层简介、socket模块介绍及代码优化、半连接池的概念
目录 传输层之TCP与UDP协议 应用层 socket模块 socket基本使用 代码优化 半连接池的概念 传输层之TCP与UDP协议 TCP与UDP都是用来规定通信方式的 通信的时候可以随心所欲的聊 ...
- 单例模式实现的多种方式、pickle序列化模块、选课系统需求分析等
目录 单例模式实现的多种方式 方式一: 方式二: 方式三 方式四 pickle序列化模块 选课系统需求分析 功能提炼 选课系统架构设计 三层架构 选课系统目录搭建 选课系统功能搭建 单例模式实现的多种 ...
- redisson分布式锁原理剖析
redisson分布式锁原理剖析 相信使用过redis的,或者正在做分布式开发的童鞋都知道redisson组件,它的功能很多,但我们使用最频繁的应该还是它的分布式锁功能,少量的代码,却实现了加锁. ...
- hexo-gitalk-评论自动初始化
第一步 申请Personal Access Token 从 Github 的 Personal access tokens 页面,点击 Generate new token 第二步 安装项目依赖 np ...
- [论文阅读] 颜色迁移-Linear Monge-Kantorovitch(MKL)
[论文阅读] 颜色迁移-Linear Monge-Kantorovitch(MKL) 文章: The Linear Monge-Kantorovitch Linear Colour Mapping f ...
- 真正“搞”懂HTTP协议06之body的玩法(理论篇)
本来啊,本来,本来我在准备完善这个鸽了四年的系列的时候,是打算按照时间的顺序来完成的,好吧.我承认那个时候考虑的稍稍稍稍稍微有些不足,就是我忽略了HTTP协议的"模块性".因为虽然 ...
- 使用echarts(可视化图表库)
一:echarts 1.简介 一个基于 JavaScript 的开源可视化图表库 echarts官网使用教程: https://echarts.apache.org/zh/index.html 2.e ...
- 电脑无法自动获取ip地址
1.按下win+r,输入cmd,打开命令提示符;2.执行ipconfig命令看下能否获取到ip地址:3.若不能,执行ipconfig /renew命令重新获取ip:4.执行ipconfig命令看下能否 ...