1 响应JSON

1.1 jackson.jar+@ResponseBody

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
web场景自动引入了json场景
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-json</artifactId>
      <version>2.3.4.RELEASE</version>
      <scope>compile</scope>
    </dependency>

给前端自动返回json数据

1、返回值解析器

同参数解析器一样,返回值解析器也有多个,当目标方法返回数据时会先通过ResponseBody注解同这些解析器进行匹配,匹配成功则进行下一步操作

2、返回值解析器原理

返回值解析器内部还有多个返回值转换器 1 返回值解析器会先判断是否支持这种类型的返回值 supportsReturnType根据注解判断 2 返回值处理器调用handleReturnValue进行处理 3 RequestResponseBodyMethodProcessor这个解析器可以处理返回值标了@ResponseBody注解的返回

    1.  利用 MessageConverters(返回值转换器) 进行处理 将数据写为json
    • 1、内容协商(浏览器默认会以请求头的方式告诉服务器他能接受什么样的内容类型)
    • 2、服务器最终根据自己自身的能力,决定服务器能生产出什么样内容类型的数据,
    • 3、SpringMVC会挨个遍历所有容器底层的 HttpMessageConverter ,看谁能处理?
      • 1、得到MappingJackson2HttpMessageConverter可以将对象写为json
      • 2、利用MappingJackson2HttpMessageConverter将对象转为json再写出去。

HTTPMessageConverter(返回值转换器)原理

HttpMessageConverter: 看是否支持将 此 Class类型的对象,转为MediaType类型的数据。 例子:Person对象转为JSON。或者 JSON转为Person

默认的MessageConverter

0 - 只支持Byte类型的 1 - String 2 - String 3 - Resource 4 - ResourceRegion 5 - DOMSource.**class \ **SAXSource.class) \ StAXSource.**class **StreamSource.**class **Source.class **6 - **MultiValueMap 7 - **true ** 8 - true 9 - 支持注解方式xml处理的。

最终 MappingJackson2HttpMessageConverter  把对象转为JSON(利用底层的jackson的objectMapper转换的)

内容协商

根据客户端接收能力不同,返回不同的媒体类型的数据

1、引入xml依赖

 <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

2、postman分别测试返回json和xml

只需要改变请求头中Accept字段。Http协议中规定的,告诉服务器本客户端可以接收的数据类型。

3、开启浏览器参数方式内容协商功能

为了方便内容协商,开启基于请求参数的内容协商功能。

spring:
    contentnegotiation:
      favor-parameter: true  #开启请求参数内容协商模式

发请求: http://localhost:8080/test/person?format=json http://localhost:8080/test/person?format=xml

确定客户端接收什么样的内容类型; 这里因为format的值是json所以,在获得这个参数之后将会优先返回json数据 1、Parameter策略优先确定是要返回json数据(获取请求头中的format的值) 2、最终进行内容协商返回给客户端json即可。

内容协商原理

  • 1、判断当前响应头中是否已经有确定的媒体类型。MediaType
  • 2、获取客户端(PostMan、浏览器)支持接收的内容类型。(获取客户端Accept请求头字段)【application/xml】
    • contentNegotiationManager 内容协商管理器 默认使用基于请求头的策略
    • **HeaderContentNegotiationStrategy  确定客户端可以接收的内容类型 **
  • 3、遍历循环所有当前系统的 MessageConverter,看谁支持操作这个对象(Person)
  • 4、找到支持操作Person的converter,把converter支持的媒体类型统计出来。例如下图中共有10种converter,但是支持转换Person只有四种,那这四种就会被放在集合当中
  • 5、这里发现 客户端需要【application/xml】。服务端能力【10种、json、xml】

  • 6、然后进行通过之前内容协商获取的客户端可支持的返回值类型,对存入集合中的四种converter进行最佳匹配
  • 7、找到最佳匹配之后,用支持将对象转为最佳匹配媒体类型 的converter。调用它进行转化 。

导入了jackson处理xml的包,xml的converter就会自动进来

WebMvcConfigurationSupport
jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);

if (jackson2XmlPresent) {
			Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();
			if (this.applicationContext != null) {
				builder.applicationContext(this.applicationContext);
			}
			messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
		}