请求处理过程4-数据响应与内容协商

在这里插入图片描述
引入web-starter后,自动引入json场景。保证数据响应。

应用于前后端分离模式
仿真调试
1.请求发过来,先到DispatcherSevelet类中doDispatch方法,
2.执行方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.获取返回值解析器(15个)
在这里插入图片描述
在这里插入图片描述
4.继续执行
在这里插入图片描述
5.拿到返回值后继续执行
在这里插入图片描述
6.寻找哪个返回值处理器可以处理,然后就调用该处理器处理
在这里插入图片描述
这个处理器可以处理: RequestResponseBodyMethodProcessor
在这里插入图片描述

7.MessageConverters处理(消息转换器),将数据转为json
在这里插入图片描述
上面这个是返回json或者字符串时调用的方法。
在这里插入图片描述
如果返回页面的话,会调用ViewNameMethodReturnValueHandler类的handleReturnValue方法。在mavContainer内填充一个view属性
在这里插入图片描述

内容协商
浏览器默认会以请求头的方式告诉服务器他能接受什么样的内容类型
服务器最终根据自己自身的能力,决定服务器能生产出什么样内容类型的数据
权重数值越大,权重越大。
在这里插入图片描述

在这里插入图片描述
9.SpringMVC会挨个遍历所有容器底层的 HttpMessageConverter ,看谁能处理?
在这里插入图片描述
HttpMessageConverter 是一个接口,消息转换器

在这里插入图片描述
能否将person对象以json的方式读进来 canread。
能否将person对象以json的方式写出去 canwrite。

HttpMessageConverter: 10个
看是否支持将 此 Class类型的对象,转为MediaType类型的数据。
例如:Person对象转为JSON。或者 JSON转为Person
在这里插入图片描述
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处理的。

10最终这个会判断成功
在这里插入图片描述
11.最终 MappingJackson2HttpMessageConverter 把对象转为JSON(利用底层的jackson的objectMapper转换的)
在这里插入图片描述

内容协商
根据客户端接收能力不同,返回不同媒体类型的数据。
引入依赖

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

再次访问就会是xml,因为xml的权重高
在这里插入图片描述

在这里插入图片描述
postman可以配置请求头的Accept
在这里插入图片描述
浏览器也可以开启基于请求参数的内容协商

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

然后请求末尾加?format=json 就返回json , 加?format=xml 就返回xml
在这里插入图片描述

内容协商原理
1、判断当前响应头中是否已经有确定的媒体类型。MediaType (第一条线处)
2、获取客户端(PostMan、浏览器)支持接收的内容类型。(获取客户端Accept请求头字段)【application/xml】(第二条线处)

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3、遍历循环所有当前系统的 MessageConverter,看谁支持操作这个对象(Person)
4、找到支持操作Person的converter,把converter支持的媒体类型统计出来。

在这里插入图片描述
5、客户端需要【application/xml】。服务端能处理的【10种、json、xml】
在这里插入图片描述
6、进行内容协商的最佳匹配媒体类型
7、用 支持 将对象转为 最佳匹配媒体类型 的converter。调用它进行转化
在这里插入图片描述
在这里插入图片描述
开启浏览器参数方式内容协商功能

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

请求路径最后加上 ‘?format=json’ ‘?format=xml’

自定义converters 返回自己定义的类型。
1.配置类中添加配置

    //1、WebMvcConfigurer定制化SpringMVC的功能
    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {

            /**
             * 自定义内容协商策略
             * @param configurer
             */

            @Override
            public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
                converters.add(new GuiguMessageConverter());
            }

        }
    }

2.自定义一个converter

/**
 * 自定义的Converter
 */
public class GuiguMessageConverter implements HttpMessageConverter<Person> {

    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return false;
    }
	//只要是Person类型的就可以写出去
    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return clazz.isAssignableFrom(Person.class);
    }

    /**
     * 服务器要统计所有MessageConverter都能写出哪些内容类型
     *
     * application/x-guigu
     * @return
     */
    @Override
    public List<MediaType> getSupportedMediaTypes() {
        return MediaType.parseMediaTypes("application/x-guigu");
    }

    @Override
    public Person read(Class<? extends Person> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return null;
    }

    @Override
    public void write(Person person, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        //自定义协议数据的写出
        String data = person.getUserName()+";"+person.getAge()+";"+person.getBirth();
        //写出去
        OutputStream body = outputMessage.getBody();
        body.write(data.getBytes());
    }
}

用Postman测试,
在这里插入图片描述
请求发过来后,判断出几个可以处理返回值的converter,然后通过内容协商,剩下自己定义的converter。因为,postman指明了要x-guigu类型的数据。

浏览器通过参数也可以获取自定义的回复
1.在配置类中增加配置

            @Override
            public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
                //Map<String, MediaType> mediaTypes
                Map<String, MediaType> mediaTypes = new HashMap<>();
                mediaTypes.put("json",MediaType.APPLICATION_JSON);
                mediaTypes.put("xml",MediaType.APPLICATION_XML);
                mediaTypes.put("gg",MediaType.parseMediaType("application/x-guigu"));
                //指定支持解析哪些参数对应的哪些媒体类型 基于参数的,浏览器发送请求
                ParameterContentNegotiationStrategy parameterStrategy = new ParameterContentNegotiationStrategy(mediaTypes);
//                parameterStrategy.setParameterName("ff");
				//基于请求头的配置,也就是postman发送请求
                HeaderContentNegotiationStrategy headeStrategy = new HeaderContentNegotiationStrategy();

                configurer.strategies(Arrays.asList(parameterStrategy,headeStrategy));
            }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值