源码理解SpringBoot理解数据响应(总体第三篇)

上两篇笔记中已经学习到了请求参数相关的处理,文章地址,接下来学习数据响应的代码流程

1、ReturnValueHandler

1)复习一下响应JSON树

(1)过程

在这里插入图片描述
在这里插入图片描述

(2)响应JSON原理

  • 断点打在这里
    在这里插入图片描述
    在这里插入图片描述
  • 从这里始终会来到这里
    在这里插入图片描述
  • 这里可以看到返回值参数解析器
    在这里插入图片描述
  • 一直点这个会经过这一步
    在这里插入图片描述
    在这里插入图片描述
  • 继续点刚才标记的那个可以来到这一步
    在这里插入图片描述
    在这里插入图片描述
    来到了这里【利用返回值处理器进行后续的处理】
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    这里返回了一个false,然后返回处理器判断是否支持这种数据类型
    在这里插入图片描述
    如果它支持的话就会再调用返回值处理器
    在这里插入图片描述
    在这里会有多次的循环遍历查找【直到找到能处理返回值的那个处理器为止】
    在这里插入图片描述
    最后匹配到了这个处理器
    在这里插入图片描述
    在这里插入图片描述

(3)到底是如何写成JSON数据的呢?

上面的过程中我们找到了处理数据的处理器,接下里详细了解一下如何处理的:
在这里插入图片描述

  • 最后的返回值是由这个来处理的
    在这里插入图片描述

  • 进入这方法看看【其实是利用MessageConverters这个进行处理,然后将数据写成JSON】
    在这里插入图片描述
    来到了这里
    在这里插入图片描述
    在这里插入图片描述

  • 这里的MediaType媒体类型,和浏览器进行类型协商和浏览器会定义好【就是内容协商】
    在这里插入图片描述
    浏览器会与服务器请求的方式告诉能接受什么的类。

  • 内容协商
    在这里插入图片描述
    这里进入浏览器和我能发的进行
    在这里插入图片描述
    这里就会找到到底能写和读
    在这里插入图片描述
    在这里插入图片描述
    既然往下面走会走到这里来
    在这里插入图片描述
    在这里插入图片描述
    这里的for循环会找到我们需要写操作的一个类型
    在这里插入图片描述
    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处理的。
    在这里插入图片描述
    在这里插入图片描述
    它会添加点东西,然后再后续的以json方式写出去。
    在这里插入图片描述
    在这里插入图片描述
    最后的最终 MappingJackson2HttpMessageConverter 把对象转为JSON(利用底层的jackson的objectMapper转换的)

2)内容协商原理

内容协商就是客户端和服务器之间进行协商,到底返回什么样子的数据类型,已达到方便的显示。

(1)看一下使用XML来处理

  • 导入依赖
    在这里插入图片描述
<dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>
  • 看响应状态
    在这里插入图片描述
    这样响应的原因是为什么呢【它把xml排在了第二位】
    在这里插入图片描述
    当使用postman测试的时候,就会发现响应的还是JSON,而修改Accept才可以响应XML。

(2)打断点来看

  • 打断点发现它根JSON也是一样的都由这个处理
    在这里插入图片描述
  • 同样的走到这一步
    在这里插入图片描述
    • 首先判断当前响应头中是否已经有确定的媒体类型,MediaType
      在这里插入图片描述

    • 没有的话进行一个全新的媒体类型【这里就是通过前端的Accept字段支持的类型进行处理,找到全部的类型】
      在这里插入图片描述
      包装对象,获取Accept字段
      在这里插入图片描述

    • 获取能产生的类型
      在这里插入图片描述
      这里获取到了比如我们刚刚导入的xml的,JSON的

    • 在这一步会找到支持xml,JSON的数据converter
      在这里插入图片描述
      在这里插入图片描述
      converter把支持的类型统计出来。
      在这里插入图片描述

    • 以我们刚刚的xml的请求为例:最后统计出来,客户端能处理xml,而服务端可以处理上面的9种吧。

    • 这里做一个最佳匹配【嵌套for循环,应该都知道吧】
      在这里插入图片描述

    • 这里就能相互匹配到
      在这里插入图片描述

    • 这里又要进行进一步的判断到底哪个能将Car对象转换为xml对象
      在这里插入图片描述
      上面是匹配到哪个能处理xml,下面一步又判断到哪个能转换。

    • 最后从这里来进行写【这里先不再详细说写的过程】

    • 最后返回到了这里
      在这里插入图片描述

    • 具体匹配的要补充一点它是有优先级的
      在这里插入图片描述

(3)小总结

在这里插入图片描述

3)基于请求参数的内容协商原理

(1)开启浏览器参数方法内容协商功能

上面介绍的内容协商原理呢是默认采用的请求头进行对比响应的。
在这里插入图片描述

(2)在浏览器通过formant设置

在这里插入图片描述

(3)那上面面能开启的原理是什么呢

同样的这里你带上了那个参数后,会在后台动态的给你确定了你指定的那个参数类型了
在这里插入图片描述
自然而然它内容协商的也会多一个
在这里插入图片描述

3)自定义MessageConverter

(1)先看点概念

实现多协议数据兼容。json、xml、自定义数据类型、@ResponseBody 响应数据出去 调用 RequestResponseBodyMethodProcessor 处理

  • Processor 处理方法返回值。通过 MessageConverter 处理。
  • 所有 MessageConverter 合起来可以支持各种媒体类型数据的操作(读、写)。
  • 内容协商找到最终的 messageConverter;

(2)响应数据

  • 浏览器请求的话响应我们的JSON
  • 如果是AJAX的话,我们响应xml
  • 如果是自定义数据类型的话,我们响应自定义数据类型。
    在这里插入图片描述
    在这里插入图片描述

(3)为什么能有那么多的Converter呢

  • 先去找找为什么能启动就有那么多默认的Converter
    在这里插入图片描述
    经过层层找下去,原来是在这里
    在这里插入图片描述
    在这里插入图片描述
    只要导入了xml,JSON依赖就能自动启用的原因就是如下
    在这里插入图片描述

只要我们想启动自用的Converter那我们就要自定义。

(4)自定义Converter

以后我们要记住,想要定制WEBMvc的功能,就在实现了WebMvcConfiguration的类里面扩展一些功能即可。

    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {

            }

            @Override
            public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {

            }

            @Override
            public void configureAsyncSupport(AsyncSupportConfigurer configurer) {

            }

            @Override
            public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {

            }

            @Override
            public void addFormatters(FormatterRegistry registry) {

            }

            @Override
            public void addInterceptors(InterceptorRegistry registry) {

            }

            @Override
            public void addResourceHandlers(ResourceHandlerRegistry registry) {

            }

            @Override
            public void addCorsMappings(CorsRegistry registry) {

            }

            @Override
            public void addViewControllers(ViewControllerRegistry registry) {

            }

            @Override
            public void configureViewResolvers(ViewResolverRegistry registry) {

            }

            @Override
            public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {

            }

            @Override
            public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {

            }

           /* @Override
            public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

            }*/

            @Override
            public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {

            }

            @Override
            public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {

            }

            @Override
            public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {

            }

            @Override
            public Validator getValidator() {
                return null;
            }

            @Override
            public MessageCodesResolver getMessageCodesResolver() {
                return null;
            }
        };
    }

这里只能进行postman测试,原因和解决办法如下

(5)postman与浏览器协商完全匹配

  • 它浏览器默认就两种:xml和JSON当你写自己的format=x-car就会错误
    在这里插入图片描述
    这些策略都已经添加好了,我们就只能自己指定了。

  • 自定义SpringMVC

@Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
                converters.add(new zidingyiMessageConverter());
            }

            @Override
            public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
                //参数支持的媒体类型
                Map<String,MediaType> mediaTypeMap = new HashMap<>();
                mediaTypeMap.put("json",MediaType.APPLICATION_JSON);
                mediaTypeMap.put("xml",MediaType.APPLICATION_ATOM_XML);
                mediaTypeMap.put("car",MediaType.parseMediaType("application/x-car"));
                ParameterContentNegotiationStrategy parameter = new ParameterContentNegotiationStrategy(mediaTypeMap);

                configurer.strategies(Arrays.asList(parameter));
            }
        };
    }
  • 此时就可以:http://localhost:8888/car?format=car进行测试了

  • 我们还可以这样设置

@Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
                converters.add(new zidingyiMessageConverter());
            }

            @Override
            public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
                //参数支持的媒体类型
                Map<String,MediaType> mediaTypeMap = new HashMap<>();
                mediaTypeMap.put("json",MediaType.APPLICATION_JSON);
                mediaTypeMap.put("xml",MediaType.APPLICATION_ATOM_XML);
                mediaTypeMap.put("car",MediaType.parseMediaType("application/x-car"));
                //设置如下的两种的匹配模式
                ParameterContentNegotiationStrategy parameter = new ParameterContentNegotiationStrategy(mediaTypeMap);

                HeaderContentNegotiationStrategy headerStrategy = new HeaderContentNegotiationStrategy();
                configurer.strategies(Arrays.asList(parameter,headerStrategy));
            }
        };
    }

有可能我们添加的自定义的功能会覆盖默认很多功能,导致一些默认的功能失效。
大家考虑,上述功能除了我们完全自定义外?SpringBoot有没有为我们提供基于配置文件的快速修改媒体类型功能?怎么配置呢?【提示:参照SpringBoot官方文档web开发内容协商章节】

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值