【Web响应处理】内容协商原理

内容协商原理

根据客户端接收能力的不同,返回不同媒体类型的数据。改变请求头中Accept字段,告诉服务器客户端可以接收的数据类型。

  1. 判断当前响应头中是否已经有确定的媒体类型,如果有就使用之前确定的媒体类型
    在这里插入图片描述

  2. 使用contentNegotiationManager内容协商管理器,默认使用基于请求头的策略,来获取客户端支持接收的内容类型,即获取请求头中的Accept字段的值
    在这里插入图片描述

  3. 获取服务器能够产生的媒体类型。循环遍历所有当前系统的MessageConverter,找到支持操作当前对象的消息转换器
    在这里插入图片描述
    在这里插入图片描述

  4. 找到支持操作当前对象的converter,把converter支持的媒体类型统计出来
    在这里插入图片描述

  5. 进行协商内容的最佳匹配媒体类型,即匹配客户端想要接收的内容类型和服务器能够产生的内容类型
    在这里插入图片描述

  6. 再次循环遍历所有MessageConverter,利用支持将对象转为最佳匹配媒体类型的converter,调用它进行转换
    在这里插入图片描述

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

开启基于请求参数的内容协商模式

spring:
  mvc:
    contentnegotiation:
      favor-parameter: true

在这里插入图片描述
在这里插入图片描述
内容协商管理器的管理策略变成了两个,一个是基于参数的内容协商策略,一个是基于请求头的内容协商策略
在这里插入图片描述
遍历所有的内容协商策略,确定客户端接收什么样的内容类型。基于请求参数的策略优先确定是要返回json数据还是xml数据,这是根据请求参数format确定的
在这里插入图片描述

自定义MessageConverter

自定义MessageConverter可以实现多协议数据兼容

  • @ResponseBody响应数据出去 调用RequestResponseBodyMethodProcessor处理
  • RequestResponseBodyMethodProcessor通过MessageConverter处理方法返回值
  • 所有 MessageConverter 合起来可以支持各种媒体类型数据的操作(读、写)
  • 内容协商找到最终的 messageConverter

自定义MessageConverter

public class MyMessageConverter implements HttpMessageConverter<Person> {
    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return false;
    }

    /**
     * 能够写Person类型的数据
     * @param clazz 传入的数据类型
     * @param mediaType 传入的媒体类型
     * @return  返回是否能够写指定的数据类型
     */
    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return clazz.isAssignableFrom(Person.class);
    }

    /**
     * 服务器要统计所有的MessageConverter都能支持哪些媒体类型
     * @return  支持的媒体类型集合
     */
    @Override
    public List<MediaType> getSupportedMediaTypes() {
        return MediaType.parseMediaTypes("application/myMediaType");
    }

    @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());
    }
}

将自定义的MessageConverte通过自动配置类,重写extendsMessageConverter()方法,来添加到容器中
在这里插入图片描述
这样通过基于请求头的策略,就可以使用自定义的媒体类型来进行内容协商

如果是基于请求参数的内容协商原理,需要在自动配置类中重写configureContentNegotiation()方法,创建一个支持自定义媒体类型的基于请求参数的内容协商策略,并注册到内容协商策略中
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值