内容协商,与content-type,httpMessageConverter

1.content-type 是指 数据在 http网络通信的时候,字符串的类型
2.请求有 发送数据的 content-type,有 可以接收的content-type
3.而 编码格式,只是 这个字符串里面的 字符的 编码格式,content-type是这个字符串的 类型
4.而有些特定的 需求 例如文件,得用特定的 content-type
5.前端 将数据 写入 请求体中的时候,要么将数据 用 messageConverter转换 成 对应的 类型的 字符串,要么 直接传对应类型的字符串

6.到了后台,首先,tomcat会用 application/www… 或者 Multiplication…,这两种 消息转换器,将字符串 转换成对应数据,封装在request.param中,然后tomcat这两种 消息转换器以外 类型的 字符串类型 就无法转换,只能在请求体中,无法被转换,而这两种消息转换器,也是依次判断,是否 canRead,如果可以read,那么 read

7.请求体中的 字符串,mvc 用 requestBody注解,一个requestBody请求处理器处理,其中 有 10多个 消息转换器,canRead(),这10多个都可以 read , 但是内容协商,看 请求的content-Type是什么,那么我们就用 那个 消息转换器 将消息转换 成 对应的数据类型

8.RequestBody和 responseBody的 请求值和返回值处理器,里面有很多 消息转换器,但是有两个 json,和 xml的,有一个条件才能加入ioc容器中,那就是 conditionalOnClass() , 也就是必须得有 这两个依赖才行

9.现在我们谈论 返回值(Person类型),在返回值的时候,有很多个 返回值处理器,来判断到底要用那个返回值处理器,我们就用 responseBody返回值处理器来做讲解。responseBody拿到 返回值后,用里面的 10多个 httpMessageConverter,来 处理 返回值, 然后遍历 这10多个 消息转换器(如果在之前,已经确定了 响应的 setContent-Type了,那么直接选择,能处理这个 mediaType的消息转换器,就不用遍历了)

canWrite(class,Media Type),看能不能把这个数据类型,以这种mediaType写出去

这时候canwrite 调用 support(class),看这个Person,能不能支持这种类型的class,如果能(这个是先判断 数据类型)

然后,看这个 class 能不能 以 Media Type写出去,如果这时候没有指定 Media Type = null , 那么会调用 消息转换器 的 getSupportMediaTypes,拿到这个 消息转换器支持的 写出的 media-Type,如果这时候指定了 Media Type,那么 这时候 消息转换器能不能处理这个class 以及 消息转换器 有哪些 media type也确定了,那么这时候回到 canWrite(class,Media Type),然后 再 看 能不能 把 这个 class
转换成 这几个(或者 指定的)Media Type中的 一个,如果可以,那么return True

canWrite(class,MediaType)的流程
1.support(class) 是否支持 这个 class类型 return true 下一步
(这一步其实 就是 确定能用的 class类型)

2.getSupportMediaType(),获取这个消息转换器支持的 mediaType(如果MediaType已经确定了,就不用这个方法了)
(这一步 其实就是 确定 能用的 MediaType类型)

3.判断 这个消息转换器 能不能 把 这个 支持的class , 转换 成 支持的MediaType(其中的一个),这时候一般 一个class类型 会对应一个 mediaType , 或者 一个都不行,如果有一个 那么 return true
(这一步就是确定,class和mediaType的对应关系,如果有一个可以对应起来的,那么就是可以写,消息转换器默认只能让一种class 对应 一种 mediaType)

如果 canWrite return true,那么就是这个消息转换器可以写,10多个消息转换器依次判断,筛选出可以写的 消息转换器

这时候的 不同的消息转换器,基本对应不同的 写出的 MediaType(如果之前已经确定了 MediaType,那么 肯定只能 有 一种消息转换器 可以支持 这个class 和 这个确定的 MediaType,意思就是说 如果已经确定了响应的 Media Type,那么 最后 一定只剩下一个 消息转换器)
这时候 看 请求的 accept-MediaType, 然后跟 我们服务器可以写的 MediaType 做内容协商,等于 两个 list《Media-Type》做比较

10.内容协商(内容协商管理器)
内容协商管理器里面默认有一个策略,就是基于请求头的
然后你可以再配置文件中开启,基于 参数列表的策略(只支持json/xml)
当然,你可以自定义内容协商策略(注册一个bean),基于参数列表但是(支持 自定义 content-type的),这时你还需要,自定义一个 httpMessageCoverter

1.accept-MediaType有 多种(一种),服务器 mediaType有多种(一种),那么这时候 这两个 list<Media-Type》就开始协商了,对比你有的,我有的,看看有没有相同的,有的话,那么把相同的 组合找出来
比如 accept = json 服务器有json的 accept = xml 服务器有xml的,这样的组合找出来,如果有多个,那么按浏览器权重或者先后顺序,来确定 accept = ?,进而确定 服务器 的

11.自定义 httpMessageConverter 创建了,然后就能 自定义 class 和 Media-Type类型了,比如 Media-Type = gg,那么 你只需要再 write方法里面(将 class -> gg类型),Media-Type = gg,只是说 将class类型转换成 gg类型的字符串,至于gg是什么类型的字符串,那是你自己定义的,然后得 创建一个 内容协商策略,可以让浏览器 可以接收 media-Type = gg,类型的字符串,这时候你服务器 返回了 gg类型的字符串,然后内容协商策略,可以接收这个 gg类型的 字符串,然后你只需要 再浏览器端 可以接收 gg类型的就行,浏览器也不认识 gg类型是什么,只是看 浏览器 gg,内容协商gg,以及服务器返回的 gg,能不能对应就行,至于gg到底是个 什么类型的字符串不管

上一篇:python leetcode刷题 (7):832.翻转图像


下一篇:leetcode刷题记录day006:48和344