Spring MVC 实现 JSON 序列化

1. 前言

WEB 项目,后端使用 JAVA 语言系,前端使用 JS 语言系。两种语言有各自的语法和数据类型,不能直接进行数据交换,这便是所谓的异构化系统数据通信的问题。

异构化系统中数据通信的基本解决思路是:借助所有语言都能识别的中间语言,如 XML、JSON…… 进行数据交换。

本节课就和大家聊聊控制器是如何把数据以 JSON 的格式传递给浏览器。本节课程,需要重点理解并掌握 @ResponseBody 注解的作用。

2. @ResponseBody

WEB 应用程序中,控制器处理过的数据,一般都是通过视图技术渲染成 HTML 后交给浏览器进行解析。最近几年,项目整体结构流行采用前后端分离模式。

什么是前后端分离结构?

传统项目,数据由后台完全处理,前端页面仅仅用来显示结果数据。

所谓前后端分离,会把一部分数据逻辑交给前端处理。也就意味着,交给前端的数据仅仅只是半成品数据,需要前端语言如 JS 进一步处理后再交给 HTML 显示。

后端一般选择以 JSON 的格式向前端进行数据传递。Spriing MVC 可以使用 @ResponseBody 完成这个操作。@ResponseBodySpring MVC 提供的一个很有意思的注解,一般放置在控制器方法的前面。

2.1 返回字符串

给出一个控制器的实例代码,这个代码很普通,不同之处在于方法前面使用了 @ResponseBody 注解。 于是,这个方法的命运被改变了。

@Controller
@RequestMapping("/json")
public class JsonAction {
	@RequestMapping("/test01")
	@ResponseBody
	public String testJson() {
		return "Hello";
	}
}

控制器方法有 @ResponseBody 注解和没有此注解,Spring MVC 对控制器方法的返回值的理解迥然不同。

  • 没有 @ResponseBody 注解:Spring MVC 会把返回值 “hello” 理解为视图逻辑名,通过视图解析器找到视图物理位置;
  • @ResponseBody 注解: Spring MVC 会把返回值直接写入响应包后交给浏览器。意味着不需要视图解析器的参与。

测试一下上面实例。

打开浏览器,在地址栏上输入:http://localhost:8888/sm-demo/json/test01

你在浏览器将看到如下图所示结果:

图片描述

2.2 返回对象

JAVA 中的数据很多时候都是以 OOP 的形式存在的,如学生对象数据、老师对象数据、用户对象数据……

那么,控制器中的方法能不能直接把数据以对象为单位写入响应包后返回给浏览器了?

如下面的实例:

@RequestMapping("/test02")
@ResponseBody
public User testJson01() {
	return new User("mk", "123");
}

打开浏览器,在地址栏上输入:http://localhost:8888/sm-demo/json/test02

在浏览器你将看到如下图所示结果:

图片描述

抛异常了。对于出错,大家应该有预感。UserJAVA 语言中的类类型,对于浏览器而言对它的了解是一片空白。但是,为什么前面返回字符串时却可以了?

那是因为字符串也是一种通用类型,浏览器没有不认识的道理,但是,User 类型,浏览器只能摸后脑勺了。

如果想让浏览器识别出 User 类型数据。想想也简单,自己编码,把对象数据转换成字符串格式。

@RequestMapping("/test03")
@ResponseBody
public String testJson03() {
	User user=new User("mk", "123");
	return user.getUserName()+","+user.getUserPassword();
}

经过上面的修改后,浏览器中能显示出数据。但是,这里会有 2 个问题需要思考一下:

  • 如前所述,前后端分离最主要的思想是让前端承担一部分数据业务逻辑。一串没有特定格式的字符串传递给前端,真要交给 JS 处理,你还真不怕 JS 烦心,你叫它如何从中识别出谁是谁;
  • 直接返回值给浏览器之前,需要通过手工编码的方式把 OOP 数据格式转换成字符串,这番折腾,劳心劳力。

好!先解决第一个问题。字符串数据类型是非结构化的,但是,可以把它转换成具有特定结构格式的 JSON 字符串。

@RequestMapping("/test04")
@ResponseBody
public String testJson04() {
	User user = new User("mk", "123");
	String json = "{"userName":"" + user.getUserName() + "","userPassWord":" + """
				+ user.getUserPassword() + """ + "}";
	return json;
	}

打开浏览器,地址栏中输入 http://localhost:8888/sm-demo/json/test04

浏览器中将显示如下信息:

图片描述

传递给浏览器的虽然还是字符串,但是是具有特定格式的 JSON 字符串,如果要交给 JS 处理,JS 表示很开心。

是的,数据格式的问题解决了,但是,编码的工作量增加了很多。

其实,你所想要的结果,Spring MVC 能轻松帮你实现。

3. Spring MVC 和 JSON

使用 JAVA 作为开发语言,Spring MVC 自然知道数据以对象的形式存在是正道。对于如何把后端的对象数据传递给前端,Spring MVC 有一套优雅的解决方案。

只需要简简单单的 2 步操作,便可以让开发者省心省力的把 OOP 数据序列化成 JSON 格式后响应给浏览器。

  1. 打开项目中的 WebConfig 类文件,在其中添加如下代码;
@Bean
public MappingJackson2HttpMessageConverter mappConverter() {
   MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter=new MappingJackson2HttpMessageConverter();
   return mappingJackson2HttpMessageConverter;
}

Tips: 顾名思义,MappingJackson2HttpMessageConverter 就是一个消息转换器,其作用就是把数据映射成 JSON 格式。

  1. Spring MVC 默认情况下使用的是 jackson 插件完成具体的 JSON 格式序列化。打开 pom.xml 文件,在其中添加 jackson 依赖。
<dependency>
   	<groupId>com.fasterxml.jackson.core</groupId>
   	<artifactId>jackson-databind</artifactId>
   	<version>2.10.0</version>
</dependency>

有了上面配置后,几乎不需要再做任何多余的事情,便能够把控制器中的 OOP 数据以 JOSN 方式序列化给浏览器。

测试下面的控制器方法实例:

@RequestMapping("/test02")
@ResponseBody
public User testJson02() {
	return new User("mk", "123");
}

控制器方法中直接返回一个对象,不用担心,Spring MVC 会自动转换成 JOSN 格式后发送给浏览器,不信,可以试一下。

再查看浏览器中的结果。

图片描述

是不是显示的很漂亮。

4. 小结

本节课程和大家一起讲解了如何在控制器中把 OOP 数据转换成 JSON 格式后传递给浏览器。开发者可以自己编码把对象数据转换成特定格式的字符串后响应给浏览器,但是,这个过程很劳心劳力。

使用 Spring MVC 框架提供的 JSON 序列化转换组件,开发者不用关心底层具体转换过程便能达到目的。框架帮开发者解决了很多共性的问题,让开发者可以有更多时间关注自己的核心逻辑。

记住!@ResponseBody 注解很重要。