jsonutil.tolist(day11-JSON处理和HttpMessageConverter)
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="https://www.cnblogs.com/liyuelian/archive/2023/02/16/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="https://www.cnblogs.com/liyuelian/archive/2023/02/16/<%=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="https://www.cnblogs.com/liyuelian/archive/2023/02/16/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 ,增加方法 ,用于响应下载文件的请求
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!