SpringBoot2核心技术与响应式编程- 数据响应与内容协商 视图解析

响应JSON
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数据;

返回值解析器

try {
			this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
		}

  selectHandler()

1.判断是不是异步返回值

2.判断是否支持这种类型的返回值

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

 

HttpMessageConverter: 看是否支持将 此 Class类型的对象,转为MediaType类型的数据。

例子:Person对象转为JSON。或者 JSON转为Person

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

 

RequestResponseBodyMethodProcessor  	
@Override
	public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
			throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

		mavContainer.setRequestHandled(true);
		ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
		ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);

		// Try even with null return value. ResponseBodyAdvice could get involved.
        // 使用消息转换器进行写出操作
		writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
	}

内容协商

postman分别测试返回json和xml

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

内容协商原理

  • 1、判断当前响应头中是否已经有确定的媒体类型。MediaType
  • 2、获取客户端(PostMan、浏览器)支持接收的内容类型。(获取客户端Accept请求头字段)【application/xml】
    • contentNegotiationManager 内容协商管理器 默认使用基于请求头的策略
    • HeaderContentNegotiationStrategy 确定客户端可以接收的内容类型 
  • 3、遍历循环所有当前系统的 MessageConverter,看谁支持操作这个对象(Person)
  • 4、找到支持操作Person的converter,把converter支持的媒体类型统计出来。
  • 5、客户端需要【application/xml】。服务端能力【10种、json、xml】
  • 6、进行内容协商的最佳匹配媒体类型
  • 7、用 支持 将对象转为 最佳匹配媒体类型 的converter。调用它进行转化 。
开启浏览器参数方式内容协商功能

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

视图解析:

    • 返回值以 forward: 开始: new InternalResourceView(forwardUrl); --> 转发request.getRequestDispatcher(path).forward(request, response);
    • 返回值以 redirect: 开始: new RedirectView() --》 render就是重定向
    • 返回值是普通字符串: new ThymeleafView()---> 

原理:

1、目标方法处理的过程中,所有数据都会被放在 ModelAndViewContainer 里面。包括数据和视图地址

2、方法的参数是一个自定义类型对象(从请求参数中确定的),把他重新放在 ModelAndViewContainer

3、任何目标方法执行完成以后都会返回 ModelAndView(数据和视图地址)。

4、processDispatchResult 处理派发结果(页面改如何响应)

  • 1、render(mv, request, response); 进行页面渲染逻辑
    • 1、根据方法的String返回值得到 View 对象【定义了页面的渲染逻辑】
    • 1、所有的视图解析器尝试是否能根据当前返回值得到View对象
    • 2、得到了 redirect:/main.html --> Thymeleaf new RedirectView()
    • 3、ContentNegotiationViewResolver 里面包含了下面所有的视图解析器,内部还是利用下面所有视图解析器得到视图对象。
    • 4、view.render(mv.getModelInternal(), request, response); 视图对象调用自定义的render进行页面渲染工作
    • RedirectView 如何渲染【重定向到一个页面】
    • 1、获取目标url地址
    • 2、response.sendRedirect(encodedURL);

 

原文地址:https://www.cnblogs.com/yxj808/p/15317851.html