简单处理json 和HttpMessageConverter
处理JSON-@ResponseBody
项目开发中,我们往往需要服务器返回的数据格式是按照json 来返回的。
应用案例
完成示意图
代码应用
创建springmvc\web\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 () { //console.log("ok ....")测试是否绑定成功 var url = this.href; var args = {"time": new Date};//这是发送数据,为了防止页面缓存 $.post( url, args, function (data) {//data 就是返回的数据,是json格式=>如果是多个json数据,可以遍历 console.log("dataa= ", data); console.log("dog.name=", data.name) console.log("dog.addresss=", data.address) }, "json" ); return false;//返回false,防止重复提交 }) }) </script> </head> <body> <h1>请求一个json数据</h1> <%-- 1.当用户点击超链接时,我们发出一个ajax请求 2. 接收到请求后,我们查看这个数据 --%> <a href="<%=request.getContextPath()%>/json/dog" id="getJson">点击获取json数据</a> </body> </html>
创建JavaBean: springmvc\src\com\web\json\Dog.java , 作为返回的数据
public class Dog { private String name; private String address; public Dog(String name, String address) { this.name = name; this.address = address; } public Dog() { } 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 + '\'' + '}'; } }
创建springmvc\src\com\web\json\JsonHandler.java
@Controller public class JsonHandler { @RequestMapping(value = "/getJson") //指定返回的数据格式json ,靠这个@ResponseBody @ResponseBody public Dog getJson() { //创建一只狗 Dog dog = new Dog(); dog.setName("大黄狗"); dog.setAddress("北京八达岭~"); return dog; } }
完成测试(页面方式), 浏览器http://localhost:8080/springmvc/json.jsp
处理JSON-@RequestBody
应用案例
说明
前面是通过表单, 或者url 请求携带参数名=参数值把数据提交给目标方法
1.给大家举例客户端发送json 字符串数据,
2.使用SpringMVC 的@RequestBody 将客户端提交的json 数据,封装成JavaBean 对象
3.再把这个javabean 以json 对象形式返回
4.完成效果示意图
代码实现
修改json.jsp, 增加发送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 () { //给id="getJson"绑定点击事件 $("#getJson").click(function () { //console.log("ok ....")测试是否绑定成功 var url = this.href; var args = {"time": new Date};//这是发送数据,为了防止页面缓存 $.post( url, args, function (data) {//data 就是返回的数据,是json格式=>如果是多个json数据,可以遍历 console.log("dataa= ", data); console.log("dog.name=", data.name) console.log("dog.addresss=", data.address) }, "json" ); return false;//返回false,防止重复提交 }) //绑定按钮点击事件, 提交json数据 //springmvc 可以在在台將json轉成對象 $("button[name='butt1']").click(function () { //目标:将userName 和 age 封装成json字符串,发送给目标方法 var url = "/springmvc/save2"; var userName = $("#userName").val(); var age = $("#age").val(); //将json对象转成json字符串 var args = JSON.stringify({"userName": userName, "age": age}); $.ajax({ url: url, data: args, type: "POST", success: function (data) { console.log("返回的data= ", data); }, //下面这个contentType参数,是指定发送数据的编码和格式 contentType: "application/json;charset=utf-8" }) }) }) </script> </head> <body> <h1>请求一个json数据</h1> <%-- 1.当用户点击超链接时,我们发出一个ajax请求 2. 接收到请求后,我们查看这个数据 --%> <a href="<%=request.getContextPath()%>/json/dog" id="getJson">点击获取json数据</a> <h1>发出一个json数据</h1> u:<input id="userName" type="text"><br/> a:<input id="age" type="text"><br/> <button name="butt1">添加用户</button> </body> </html>
修改JsonHandler.java , 增加处理json 代码, 注意:这里用的是@PostMapping , 等价:@RequestMapping(method = RequestMethod.POST)
@PostMapping("/save2") @ResponseBody public User save2(@RequestBody User user){ //将前端传过来的数据以json 的格式相应回浏览器 System.out.println("user~= " + user); return user ; }
增加JavaBean : User.java
public class User { private String userName; private Integer age; public User(String userName, Integer age) { this.userName = userName; this.age = age; } public User() { } 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 + '}'; } }
完成测试(页面方式), 浏览器输入http://localhost:8080/springmvc/json.jsp
处理JSON-注意事项和细节
- 1.目标方法正常返回JSON 需要的数据, 可以是一个对象, 也可以是一个集合[举例]
- 2.前面是返回一个Dog 对象->转成Json 数据格式返回
- 3.@ResponseBody 可以直接写在controller 上,这样对所有方法生效
应用实例:
修改JsonHandler.java
//@Controller //@ResponseBody @RestController public class JsonHandler { /** * 1. 目标方法 @ResponseBody,表返回的数据是json格式 * 2. springmvc底层根据目标方法@ResponseBody, 返回指定格式, 根据的http请求来进行处理 * 3. 底层原理我们在前面自定义@ResponseBody说过, 这里原生的springmvc使用转换器 */ @RequestMapping(value = "/json/dog") //@ResponseBody public Dog getJson() { //返回对象 //springmvc会根据你的设置,转成json格式数据返回 Dog dog = new Dog(); dog.setName("大黄狗"); dog.setAddress("小新的家"); return dog; } //编写方法,以json格式返回多个Dog @RequestMapping(value = "/json/dogs") //@ResponseBody public List<Dog> getJsons() { List<Dog> dogs = new ArrayList<>(); dogs.add(new Dog("大黄狗", "小新的家")); dogs.add(new Dog("大黄狗2", "小新2的家")); dogs.add(new Dog("大黄狗3", "小新3的家")); return dogs; /** * 1. @RequestBody User user 在形参指定了 @RequestBody * 2. springmvc就会将提交的json字符串数据填充给指定Javabean */ @RequestMapping(value = "/save2") //@ResponseBody public User save2(@RequestBody User user) { //将前台传过来的数据 以json的格式相应回浏览器 System.out.println("user~= " + user); return user; } }
完成测试。
小结
@ResponseBody + @Controller 可以直接写成@RestController , 我们看一下源码!
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller @ResponseBody public @interface RestController { }
HttpMessageConverter
基本说明
SpringMVC 处理JSON-底层实现是依靠HttpMessageConverter来进行转换的。
工作机制简图
处理JSON-底层实现(HttpMessageConverter)
1.使用HttpMessageConverter 将请求信息转化并绑定到处理方法的入参中, 或将响应结果转为对应类型的响应信息,
Spring 提供了两种途径:
√ 使用@RequestBody / @ResponseBody 对目标方法进行标注。
√ 使用HttpEntity / ResponseEntity 作为目标方法的入参或返回值。
2.当控制器处理方法使用到@RequestBody/@ResponseBody 或HttpEntity/ResponseEntity 时,
Spring 首先根据请求头或响应头的Accept 属性选择匹配的HttpMessageConverter,
进而根据参数类型或泛型类型的过滤得到匹配的HttpMessageConverter, 若找不到可用的HttpMessageConverter 就会报错。
Dubug 源码-梳理一下