一.返回值处理的原理
1.json数据的处理
①json数据的使用
- 引入web后已经引入了json的依赖
web场景自动引入了json场景
org.springframework.bootspring-boot-starter-json2.3.4.RELEASEcompile
- jackson.jar+@ResponseBody
- 此时可自动给前端返回json数据
②json数据的使用的原理
- 返回一个Person对象,在前端中是json字符串
- 有返回值解析器(在方法返回值之后,利用返回值处理器returnvaluehandlers(15)处理)
- 有返回值
- 寻找哪个返回值处理器来处理返回值(返回值的值,返回值的类型)
- 判断是否支持这种类型的返回值(如果支持,调用返回值处理器进行处理)
- 支持哪些返回(返回值处理器)
- ModelAndView,Model,View,ResponseEntity,…
- RequestResponseBodyProcesser(其中会判断是否标了@ResponseBody注解)此时选择
- 此时看 RequestResponseBodyProcesser返回值处理器如何将返回值People返回json数据?使用消息转换器messageConverters来写出
- 内容协商(浏览器默认请求头方式要什么内容,就已经告诉后台要什么)权重优先接受什么
- 从request域中获得acceptabletypes(浏览器能接受什么数据)
- 然后获得producibletypes(服务器能返回什么类型数据)
- 两者开始循环(循环哪一个匹配)决定浏览器接受json
- 最终根据自身能力决定服务器能生产什出什么样内容类型的数据
- 得到写出内容类型json
- 判断所有的(循环)messageConverters(共有10个)消息转换器能支持people转换json(messageConverter里面有 能否读什么数据,能否写什么数据)
- 0 支持返回值byte类型 1 String 2String 3Resource 4.5.6.
- 7 mappingJackson2messageConverte(支持所有类型,无论什么都返回true)8.9.
- 用mappingJackson2messageConverte 中的write方法
- 把people转(利用底层的jackson包)json然后写入response
2.内容协商流程MessageConverter(读写)
- 功能(根据客户端接受能力不同,返回不同媒体类型的数据)
- 加入依赖jackson和xml
- 有时候返回jackson有时候返回xml(和请求头accpet字段有关)
- accept = application/xml
- accept = application/json
- 执行的handler方法后有返回值后
- 获取客户端支持的内容类型(获取客户端accept请求头字段)
- 遍历循环所有当前系统的messageconverter,看谁支持操作这个对象(people)
- 找到支持返回值为people类型的converter,把所有(第一次用)converter支持的媒体类型统计出来(json,xml数据)
- 而客户端需要application/xml,服务端中能转换10[json,xml]
- 两个for循环,客户端和服务端匹配需要和转换的类型(决定要用xml)
- (第二次用)找到转换people到xml的messageConverter
- 用messageConverter把people转换到xml
- 注意:
最佳匹配原则,如果浏览器中也传入多个可供返回的数据,浏览器中的 accept中的类型数据会有权重,xml 0.9 json 0.8 ,即在for循环中我们优先匹配到xml,然后才是json数据
方便内容协商
- 可以开启基于请求参数的内容协商(默认是请求头)
- 在配置文件中 配置一个 favor-parameter:true(开启参数的内容协商)
- 在Http请求中加入参数 format=json
- 为什么这个效果?
- 在获取客户端支持的内容类型时通过参数获取
- 在获取客户端支持的内容类型会有两个策略(默认为从请求头获取,然后返回为medietype)
- 现在多了一个策略(从参数获取然后返回为mediatype)
- 在获取时通过循环两个策略来获取浏览器支持的medietype(新加的策略优先)
3.自定义converter(利用请求头中的accept)
- 解决问题:app发请求,返回自定义协议数据 (属性值1;属性值2;)
[application/x-guigu] xxxConverter - 解决步骤
- 添加自定义的messageConverter进系统底层
- 系统底层统计出所有的messageConverter能操作哪些类型
- 客户端内容协商
- 注意:导入了jackson处理xml的包,xml的converter就回自动进来
判断是否导了包,如果导了包,则创建jackon2xmlpresent - 自定义
- 在webmvcConfigure的入口中添加配置即可(重写方法)
- 先写一个converter类继承httpmessageConverter并重写里面的方法
- canwrite方法直接返回 true(值是否为person类型)
- getsupportMediatypes() 方法返回自定义类型集合(application/x-guigu)
- write() 自定义数据协议的写出 将形参的的person的每个属性用;分割拼接为字符串,利用形参的outputMessage(response)来将字符串写出到response中
- 重写extendMessageConverters方法,在其中converters.add(我们自己创建的converter)
4.自定义协商策略(利用参数内容协商)
- 策略中只规定了两者(xml和json)
- 在webmvcConfigure的入口中添加配置即可(重写方法)
- 重写configureContentNegotiation(自定义内容协商策略,只剩自己的了)
- 创建一个新的参数内容协商策略(也可以创建一个请求头内容协商策略)
- 指定该策略支持解析哪个参数对应的哪些媒体类型
(“json”,mediaType.application_json)
(“gg”,mediaType.parseMediaType(“application/x-aguigu”)) - 将该策略配置到configurer.stratregeies()中
- 以前的内容协商策略(基于参数的,基于请求头的)
- 现在重新定义了基于参数的内容协商策略
- 如果我们自定义添加功能,可能覆盖默认功能。需要添加默认行为