游侠的博客 游侠的博客
首页
  • 论文笔记
  • 一些小知识点

    • pytorch、numpy、pandas函数简易解释
  • 《深度学习500问》
开发
技术
更多
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Ranger

一名在校研究生
首页
  • 论文笔记
  • 一些小知识点

    • pytorch、numpy、pandas函数简易解释
  • 《深度学习500问》
开发
技术
更多
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Vue

  • SpringBoot2

  • JavaWeb

  • SSM

  • SpringBoot3

    • 一、SpringBoot3快速入门
    • 二、SpringBoot核心机制了解
    • 三、SpringBoot的核心技能
    • 四、WebMvcAutoConfiguration原理
    • 五、SpringBootWeb开发-Web场景
    • 六、SpringBootWeb开发-静态资源与路径匹配
    • 七、SpringBootWeb开发-内容协商
      • 1. 多端内容适配
        • 1. 默认规则
        • 2. 效果演示
        • 3. 配置协商规则与支持类型
      • 2. 内容协商原理-HttpMessageConverter
        • 1. @ResponseBody由HttpMessageConverter处理
        • 2. WebMvcAutoConfiguration提供几种默认HttpMessageConverters
      • 3. 自定义内容返回
        • 1. 增加yaml返回支持
        • 2. 思考:如何增加其他
        • 3. HttpMessageConverter的示例写法
    • 八、SpringBootWeb开发-模板引擎
    • 九、SpringBootWeb开发-国际化与错误处理
    • 十、SpringBootWeb开发-嵌入式容器
    • 十一、SpringBootWeb开发-SpringMVC所有常用特性配置
    • 十二、SpringBootWeb开发-Web新特性
    • 十三、SpringBoot-整合SSM场景
    • 十四、SpringBoot-基础特性
    • 十五、SpringBoot-核心原理
    • 十六、SpringBoot场景整合-环境准备
    • 十七、SpringBoot场景整合-Redis
    • 十八、SpringBoot场景整合-接口文档
    • 十九、SpringBoot场景整合-远程调用
    • 二十、SpringBoot场景整合-消息服务
    • 二十一、SpringBoot场景整合-Web安全
    • 二十二、SpringBoot场景整合-可观测性
    • 二十三、SpringBoot场景整合-AOT
  • 技术
  • SpringBoot3
yangzhixuan
2023-06-05
目录

七、SpringBootWeb开发-内容协商

一套系统适配多端数据返回

image

# 1. 多端内容适配

# 1. 默认规则

  1. SpringBoot 多端内容适配。

    1. 基于请求头内容协商:(默认开启)

      1. 客户端向服务端发送请求,携带HTTP标准的Accept请求头。

        1. Accept: application/json、text/xml、text/yaml
  2. 服务端根据客户端请求头期望的数据类型进行动态返回

    1. 基于请求参数内容协商:(需要开启)

      1. 发送请求 GET /projects/spring-boot?format=json
  3. 匹配到 @GetMapping("/projects/spring-boot")

  4. 根据参数协商,优先返回 json 类型数据【需要开启参数匹配设置】

  5. 发送请求 GET /projects/spring-boot?format=xml,优先返回 xml 类型数据

# 2. 效果演示

请求同一个接口,可以返回json和xml不同格式数据

  1. 引入支持写出xml内容依赖
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>
1
2
3
4
  1. 标注注解
@JacksonXmlRootElement  // 可以写出为xml文档
@Data
public class Person {
    private Long id;
    private String userName;
    private String email;
    private Integer age;
}
1
2
3
4
5
6
7
8
  1. 开启基于请求参数的内容协商
# 开启基于请求参数的内容协商功能。 默认参数名:format。 默认此功能不开启
spring.mvc.contentnegotiation.favor-parameter=true
# 指定内容协商时使用的参数名。默认是 format
spring.mvc.contentnegotiation.parameter-name=type
1
2
3
4
  1. 效果

image

image

# 3. 配置协商规则与支持类型

  1. 修改内容协商方式
#使用参数进行内容协商
spring.mvc.contentnegotiation.favor-parameter=true  
#自定义参数名,默认为format
spring.mvc.contentnegotiation.parameter-name=myparam 
1
2
3
4
  1. 大多数 MediaType 都是开箱即用的。也可以自定义内容类型,如:
spring.mvc.contentnegotiation.media-types.yaml=text/yaml
1

# 2. 内容协商原理-HttpMessageConverter

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

# 1. @ResponseBody由HttpMessageConverter处理

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

  1. 如果controller方法的返回值标注了 @ResponseBody注解

    1. 请求进来先来到DispatcherServlet的doDispatch()进行处理

    2. 找到一个 HandlerAdapter适配器。利用适配器执行目标方法

    3. RequestMappingHandlerAdapter来执行,调用invokeHandlerMethod()来执行目标方法

    4. 目标方法执行之前,准备好两个东西

      1. HandlerMethodArgumentResolver:参数解析器,确定目标方法每个参数值
      2. HandlerMethodReturnValueHandler:返回值处理器,确定目标方法的返回值改怎么处理
    5. RequestMappingHandlerAdapter 里面的invokeAndHandle()真正执行目标方法

    6. 目标方法执行完成,会返回返回值对象

    7. 找到一个合适的返回值处理器 HandlerMethodReturnValueHandler

    8. 最终找到 RequestResponseBodyMethodProcessor能处理 标注了 @ResponseBody注解的方法

    9. RequestResponseBodyMethodProcessor 调用writeWithMessageConverters,利用MessageConverter把返回值写出去

上面解释:@ResponseBody由HttpMessageConverter处理

  1. HttpMessageConverter 会先进行内容协商
    1. 遍历所有的MessageConverter看谁支持这种内容类型的数据
    2. 默认MessageConverter有以下(8、9是自己加的支持XML的MessageConverter) image
    3. 最终因为要json所以MappingJackson2HttpMessageConverter支持写出json
    4. jackson用ObjectMapper把对象写出去

# 2. WebMvcAutoConfiguration提供几种默认HttpMessageConverters

  • EnableWebMvcConfiguration通过 addDefaultHttpMessageConverters添加了默认的MessageConverter;如下:

    • ByteArrayHttpMessageConverter: 支持字节数据读写
    • StringHttpMessageConverter: 支持字符串读写
    • ResourceHttpMessageConverter:支持资源读写
    • ResourceRegionHttpMessageConverter: 支持分区资源写出
    • AllEncompassingFormHttpMessageConverter:支持表单xml/json读写
    • MappingJackson2HttpMessageConverter: 支持请求响应体Json读写

默认8个:

image

系统提供默认的MessageConverter 功能有限,仅用于json或者普通返回数据。额外增加新的内容协商功能,必须增加新的HttpMessageConverter

# 3. 自定义内容返回

# 1. 增加yaml返回支持

导入依赖

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
1
2
3
4

把对象写出成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);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13

编写配置

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

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

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

# 2. 思考:如何增加其他

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

# 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
编辑 (opens new window)
上次更新: 2024/05/30, 07:49:34
六、SpringBootWeb开发-静态资源与路径匹配
八、SpringBootWeb开发-模板引擎

← 六、SpringBootWeb开发-静态资源与路径匹配 八、SpringBootWeb开发-模板引擎→

最近更新
01
tensor比较大小函数
05-30
02
Large Language Models can Deliver Accurate and Interpretable Time Series Anomaly Detection
05-27
03
半监督学习经典方法 Π-model、Mean Teacher
04-10
更多文章>
Theme by Vdoing | Copyright © 2023-2024 Ranger | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式