0
点赞
收藏
分享

微信扫一扫

Flutter类

小a草 2024-09-13 阅读 18

十,Spring Boot 的内容协商的详细剖析(附+Debug调试说明)

文章目录


1. 基本介绍

根据客户端接收能力不同,SpringBoot返回不同媒体类型的数据。

比如:客户端 Http请求 Accept:application/xml 则返回xml数据,客户端 Http 请求 Accept:application/json 则返回json数据。

关于 内容协商的 类是:AbstractJackson2HttpMessageConverter.java 这个类

在这里插入图片描述

在这里插入图片描述

2. 准备工作

导入相关的 jar 依赖。

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.rainbowsea</groupId>
    <artifactId>springboot_jsonxml</artifactId>
    <version>1.0-SNAPSHOT</version>


    <!--    导入SpringBoot 父工程-规定写法-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
    </parent>

    <!--    导入web项目场景启动器:会自动导入和web开发相关的jar包所有依赖【库/jar】-->
    <!--    后面还会在说明spring-boot-starter-web 到底引入哪些相关依赖-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--引入lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

</project>

准备好,测试的 Bean 类,两个,分别为 Car,Monster 类,这里我使用了 lombok 插件自动生成 set和 get方法。关于这部分的内容大家可以移步至:✏️✏️✏️ 六,Spring Boot 容器中 Lombok 插件的详细使用,简化配置,提高开发效率_lombok的getter和setter怎么用-CSDN博客

在这里插入图片描述

package com.rainbowsea.bean;


import lombok.Data;


@Data
public class Car {
    private String name;
    private Double price;

}

package com.rainbowsea.bean;


import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;


@Component
@Setter
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Monster {
    private Integer id;
    private String name;
    private Boolean isMarried;
    private Integer age;
    private Date birth;
    private Car car;
    private String[] skill;
    private List<String> hobby;
    private Map<String,Object> wife;
    private Set<Double> salaries;
    private Map<String,List<Car>> cars;

}

相关的 Controller 控制器,处理相关的请求路径映射

在这里插入图片描述

package com.rainbowsea.controller;


import com.rainbowsea.bean.Car;
import com.rainbowsea.bean.Monster;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Date;

@Controller
public class ResponseController {


    // 返回 Monster 数据-要求以JSON格式返回
    @GetMapping("/get/monster")
    @ResponseBody
    public Monster getMonster() {

        // monster 对象是从DB数据库获取-这里老师模拟一个monster对象
        Monster monster = new Monster();
        monster.setId(100);
        monster.setName("奔波霸");
        monster.setAge(200);
        monster.setIsMarried(false);
        monster.setBirth(new Date());
        Car car = new Car();
        car.setName("奔驰");
        car.setPrice(222.2);
        monster.setCar(car);

        return monster;
    }

}

项目的/应用程序的启动场景

在这里插入图片描述

package com.rainbowsea;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication  // 标注项目的启动场景
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

运行程序,打开浏览器输入:http://localhost:8080/get/monster 。运行测试

在这里插入图片描述

3. 内容协商的本质

从上述运行结果的返回来看,显示的是 JSON格式的数据。

为什么显示的是 JSON格式的数据。显示返回的是什么样的格式的数据是由:

下面我们导入xml 数据格式的依赖,再进行一个测试

在这里插入图片描述

<!--        引入 处理xml 的依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.rainbowsea</groupId>
    <artifactId>springboot_jsonxml</artifactId>
    <version>1.0-SNAPSHOT</version>


    <!--    导入SpringBoot 父工程-规定写法-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
    </parent>

    <!--    导入web项目场景启动器:会自动导入和web开发相关的jar包所有依赖【库/jar】-->
    <!--    后面还会在说明spring-boot-starter-web 到底引入哪些相关依赖-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--引入lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--        引入 处理xml 的依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>

    </dependencies>

</project>

重新运行程序,打开浏览器输入:http://localhost:8080/get/monster 。运行测试
在这里插入图片描述

这回返回的就是 xml 格式的数据了,因为我们这里配置了 json和 xml 两种格式的依赖,但是,xml数据格式的优先级为0.9比 json 的优先级更高,所以显示的是 xml 格式的数据类型。

同样我们也进行一个 Debug 断点调试。还是一样的。

在这里插入图片描述

在这里插入图片描述

我们前端显示的也是 xml 格式的数据。
在这里插入图片描述


4. 内容协商:注意事项和使用细节

  1. Postman 可以通过修改 Accept 的值,来返回不同的数据格式。感兴趣的大家可以自行去下载,试试。官网地址:https://www.postman.com/

在这里插入图片描述

  1. 对于浏览器,我们无法修改其 Accept的值,怎么办?解决方案:开启支持基于请求参数的内容协商功能

  2. 修改 application.yaml(必须在类路径"resources"下才行),开启基于请求参数的内容协商功能。

在这里插入图片描述

spring:
  mvc:
    contentnegotiation:
      favor-parameter: true # 开启基于请求参数的内容协商功能
      #?format=json

其实修改的就是:WebMvcProperties类当中的 内部类 Contentnegotiation的 favorParameter 的值。

在这里插入图片描述

在这里插入图片描述

配置好以后,重新启动程序,打开浏览器,注意需要在我们地址后面加上 ?format=xxx ,xxx 就是你要转换显示为什么样格式的数据的值。比如:

  • ?format=json 就是在前端以 json格式的数据展示。
  • ?format=xml 就是在前端以 xml 格式的数据展示。
  • http://localhost:8080/get/monster?format=json

在这里插入图片描述

  • http://localhost:8080/get/monster?format=xml

在这里插入图片描述

5. 总结:

  1. 内容协商就是:根据客户端接收能力不同,SpringBoot返回不同媒体类型的数据。

    比如:客户端 Http请求 Accept:application/xml 则返回xml数据,客户端 Http 请求 Accept:application/json 则返回json数据。

  2. 内容协商的返回值是由:

  3. 请求头当中的 Accept 属性的值所决定的。Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
xml 为 0.9 优先级更高
*/*(其它的数据类型,包括 json格式的字符) 为 0.8 稍微低一点。
  1. 参数format是规定好的,在开启请求参数的内容协商功能后,SpringBoot底层 ParameterContentNegotiationStrategy 会通过 format 来接收参数,然后返回对应的媒体类型/数据格式,当然format=xxx,这个xxx媒体类型/数据格式是SpringBoot可以
    处理的才行,不能乱写。也注意是英文的 ?
  2. 我们自己指定一个内容协商的参数名,修改掉了默认的 format 的参数了,就不再是默认的 format而是,rainbowsea=json ,默认的(format 就不可以再用了,已经失效了)失效了。

6. 最后:

举报

相关推荐

0 条评论