SpringBoot3---核心特性---2、Web开发II

在这里插入图片描述
                       星光下的赶路人star的个人主页

                      大鹏一日同风起,扶摇直上九万里

1、内容协商

一套系统适配多端数据返回
在这里插入图片描述

1.1 多端内容适配

1.1.1 默认规则

1、SpringBoot多端内容适配
1.1 基于请求头内容协商(默认开启)
1.1.1 客户端向服务端发送请求,携带HTTP标准的Accept请求头
1.1.1.1 Accept:application/json、text/xml、text/yaml
1.1.1.2 服务端根据客户端请求头期望的数据类型进行动态返回

1.2 基于请求参数内容协商:(需要开启)
1.2.1 发送请求Get/projects.spring-boot?format=json
1.2.2 匹配到@GetMapping(“/projects/spring-boot”)
1.2.3 根据参数协商,优先返回json类型数据【需要开启参数匹配设置】
1.2.4 发送请求Get/projects/spring-boot?format=xml,优先返回xml类型的数据

1.1.2 效果演示

请求同一个接口,可以返回json和xml不同格式数据
1、引入支持写出xml内容依赖

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

2、标注注解

@JacksonXmlRootElement  // 可以写出为xml文档
@Data
public class Person {
    private Long id;
    private String userName;
    private String email;
    private Integer age;
}

3、开启基于请求参数的内容协商

# 开启基于请求参数的内容协商功能。 默认参数名:format。 默认此功能不开启
spring.mvc.contentnegotiation.favor-parameter=true
# 指定内容协商时使用的参数名。默认是 format
spring.mvc.contentnegotiation.parameter-name=type

4、效果
在这里插入图片描述
在这里插入图片描述

1.1.3 配置协商规则与支持类型

1、修改内容协商方式

#使用参数进行内容协商
spring.mvc.contentnegotiation.favor-parameter=true  
#自定义参数名,默认为format
spring.mvc.contentnegotiation.parameter-name=myparam 

2、大多数 MediaType 都是开箱即用的。也可以自定义内容类型,如:

spring.mvc.contentnegotiation.media-types.yaml=text/yaml

1.2 自定义内容返回

1.2.1 增加yaml返回支持

导入依赖

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

把对象写出成YAML

    public static void main(String[] args) throws JsonProcessingException {
        Person person = new Person();
        person.setId(1L);
        person.setUserName("张三");
        person.setEmail("aaa@qq.com");
        person.setAge(18);

        YAMLFactory factory = new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
        ObjectMapper mapper = new ObjectMapper(factory);

        String s = mapper.writeValueAsString(person);
        System.out.println(s);
    }

编写配置

#新增一种媒体类型
spring.mvc.contentnegotiation.media-types.yaml=text/yaml

增加HttpMessageConverter组件,专门负责把对象写出为yaml格式

    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override //配置一个能把对象转为yaml的messageConverter
            public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
                converters.add(new MyYamlHttpMessageConverter());
            }
        };
    }

1.2.2 思考:如何增加其它

● 配置媒体类型支持:
○ spring.mvc.contentnegotiation.media-types.yaml=text/yaml
● 编写对应的HttpMessageConverter,要告诉Boot这个支持的媒体类型
○ 按照3的示例
● 把MessageConverter组件加入到底层
○ 容器中放一个WebMvcConfigurer 组件,并配置底层的MessageConverter

1.2.3 HttpMessageConverter的示例写法

public class MyYamlHttpMessageConverter extends AbstractHttpMessageConverter<Object> {

    private ObjectMapper objectMapper = null; //把对象转成yaml

    public MyYamlHttpMessageConverter(){
        //告诉SpringBoot这个MessageConverter支持哪种媒体类型  //媒体类型
        super(new MediaType("text", "yaml", Charset.forName("UTF-8")));
        YAMLFactory factory = new YAMLFactory()
                .disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
        this.objectMapper = new ObjectMapper(factory);
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        //只要是对象类型,不是基本类型
        return true;
    }

    @Override  //@RequestBody
    protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return null;
    }

    @Override //@ResponseBody 把对象怎么写出去
    protected void writeInternal(Object methodReturnValue, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

        //try-with写法,自动关流
        try(OutputStream os = outputMessage.getBody()){
            this.objectMapper.writeValue(os,methodReturnValue);
        }

    }
}

1.3 内容协商原理-HttpMessageConverter

● HttpMessageConverter 怎么工作?合适工作?
● 定制 HttpMessageConverter 来实现多端内容协商
● 编写WebMvcConfigurer提供的configureMessageConverters底层,修改底层的MessageConverter

1.3.1 @ResponseBody由HttpMessageConverter处理

标注了@ResponseBody的返回值 将会由支持它的 HttpMessageConverter写给浏览器

  1. 如果controller方法的返回值标注了 @ResponseBody 注解
    1.1. 请求进来先来到DispatcherServlet的doDispatch()进行处理
    1.2. 找到一个 HandlerAdapter 适配器。利用适配器执行目标方法
    1.3. RequestMappingHandlerAdapter来执行,调用invokeHandlerMethod()来执行目标方法
    1.4. 目标方法执行之前,准备好两个东西
    1.4.1. HandlerMethodArgumentResolver:参数解析器,确定目标方法每个参数值
    1.4.2. HandlerMethodReturnValueHandler:返回值处理器,确定目标方法的返回值改怎么处理
    1.5. RequestMappingHandlerAdapter 里面的invokeAndHandle()真正执行目标方法
    1.6. 目标方法执行完成,会返回返回值对象
    1.7. 找到一个合适的返回值处理器 HandlerMethodReturnValueHandler
    1.8. 最终找到 RequestResponseBodyMethodProcessor能处理 标注了 @ResponseBody注解的方法
    1.9. RequestResponseBodyMethodProcessor 调用writeWithMessageConverters ,利用MessageConverter把返回值写出去

上面解释:@ResponseBody由HttpMessageConverter处理
2. HttpMessageConverter 会先进行内容协商
2.1. 遍历所有的MessageConverter看谁支持这种内容类型的数据
2.2. 默认MessageConverter有以下
在这里插入图片描述
2.3. 最终因为要json所以MappingJackson2HttpMessageConverter支持写出json
2.4. jackson用ObjectMapper把对象写出去

1.3.2 WebMvcAutoConfiguration提供几种默认HttpMessageConverters

● EnableWebMvcConfiguration通过 addDefaultHttpMessageConverters添加了默认的MessageConverter;如下:
○ ByteArrayHttpMessageConverter: 支持字节数据读写
○ StringHttpMessageConverter: 支持字符串读写
○ ResourceHttpMessageConverter:支持资源读写
○ ResourceRegionHttpMessageConverter: 支持分区资源写出
○ AllEncompassingFormHttpMessageConverter:支持表单xml/json读写
○ MappingJackson2HttpMessageConverter: 支持请求响应体Json读写
默认8个:
在这里插入图片描述
系统提供默认的MessageConverter 功能有限,仅用于json或者普通返回数据。额外增加新的内容协商功能,必须增加新的HttpMessageConverter

在这里插入图片描述
                      您的支持是我创作的无限动力

在这里插入图片描述
                      希望我能为您的未来尽绵薄之力

在这里插入图片描述
                      如有错误,谢谢指正;若有收获,谢谢赞美

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星光下的赶路人star

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值