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

news2024/12/23 3:15:51

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

文章目录

  • 十,Spring Boot 的内容协商的详细剖析(附+Debug调试说明)
  • 1. 基本介绍
  • 2. 准备工作
  • 3. 内容协商的本质
  • 4. 内容协商:注意事项和使用细节
  • 5. 总结:
  • 6. 最后:


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格式的数据。显示返回的是什么样的格式的数据是由:

请求头当中的 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 稍微低一点。

而这里之所以显示的 JSON 格式的数据,是因为在我们pom.xml 文件中导入的 spring boot 依赖当中包含了 json 数据格式的 jar 依赖。

在这里插入图片描述

而没有 xml 的数据格式的 jar 依赖,自然就是优先为 json 你有的数据格式的jar依赖为准了。

我们可以 Debug 看看。

我们在 AbstractJackson2HttpMessageConverter.java 类当中的 writeInternal() 的方法当中打上 断点

在这里插入图片描述

在这里插入图片描述

直到走到这里,我们查看 generator的值:发现是 JSON。这就没错了,我们仅仅是spring boot 框架种自行配置了 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 格式的数据展示。

注意:参数format是规定好的,在开启请求参数的内容协商功能后,SpringBoot底层 ParameterContentNegotiationStrategy 会通过 format 来接收参数,然后返回对应的媒体类型/数据格式,当然format=xxx,这个xxx媒体类型/数据格式是SpringBoot可以
处理的才行,不能乱写。
也注意是英文的 ?

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

在这里插入图片描述

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

在这里插入图片描述

其实这个 format 的值是:ParameterContentNegotiationStrategy 类当中的 parameterName 属性值。

在这里插入图片描述

这个我们也可以修改这个值,指定一个内容协商的参数名,就不再是默认的 format而是我们自己定义的一个参数名了。

还是在 application.yaml 文件当中配置,增加上一个属性。

这里我们指定**内容协商的参数名为,rainbowsea

在这里插入图片描述

spring:
  mvc:
    contentnegotiation:
      favor-parameter: true # 开启基于请求参数的内容协商功能
      #?format=json
      parameter-name: rainbowsea # 指定一个内容协商的参数名,就不再是默认的 format而是
      # ?rainbowsea=json ,默认的失效了

重新启动程序,浏览器运行测试:

  • http://localhost:8080/get/monster?rainbowsea=json
  • http://localhost:8080/get/monster?rainbowsea=xml

在这里插入图片描述

需要注意的是: 我们自己指定一个内容协商的参数名,修改掉了默认的 format 的参数了,就不再是默认的 format而是,rainbowsea=json ,默认的(format 就不可以再用了,已经失效了)失效了。

在这里插入图片描述

默认的 format 已经失效了, 无论我们配置=json,还是 xml ,都返回的是 xml 格式类型的数据

。因为 xml 优先级是0.9 比较高的,所以返回的就是默认优先级高的 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. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2130917.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

k8s环境搭建(续)

查看节点信息并做快照 kubectl get nodes 将components.yml文件上传到master主机 创建nginx&#xff0c;会在添加一个新的pod kubectl run nginx --imagesnginx:latest 查看nginx的pod信息 [rootk8s-master ~]# kubectl get po -Aowide|grep nginx 出现错误&#xff0c;查…

Python | Leetcode Python题解之第399题除法求值

题目&#xff1a; 题解&#xff1a; class Solution:def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:# 构造图graph defaultdict(list)for (u, v), value in zip(equations, values):graph[u].appen…

Vite + Electron 时,Electron 渲染空白,静态资源加载错误等问题解决

问题 如果在 electron 里直接引入 vite 打包后的东西&#xff0c;那么有些资源是请求不到的 这是我的引入方式 根据报错&#xff0c;我们来到 vite 打包后的路径看一看 &#xff0c;修改一下 dist 里的文件路径试了一试 修改后的样子&#xff0c;发现是可以的了 原因分析 …

react 基础语法

前置知识 类的回顾 通过class关键字定义一个类 类名首字母大写 class类有constructor构造器 new 一个类得到一个实例 类还有方法&#xff0c;该方法也会在其原型上 static静态数据&#xff0c;访问静态属性通过 类名.id getter和setter getter&#xff1a;定义一个属性&…

渠道分析促增长,App如何靠渠道来源追踪构建评估体系

只要接触市场或运营工作&#xff0c;流量的投入产出细节就是必定要被追问的问题&#xff0c;碎片化的渠道营销和投入资源没有精细化管理的话&#xff0c;势必要面临以下诸多问题&#xff1a; 做了这么多地方的投放&#xff0c;哪个渠道效果最好&#xff1f;某个大主播确实给我…

猫鼠游戏: KaijiK病毒入侵溯源分析

1. 事件背景 近期&#xff0c;网宿平台某客户在使用云主机工作的时候突然出现主机卡顿&#xff0c;连接不稳定&#xff0c;网络断开的情况&#xff0c;并且收到了网宿主机入侵检测产品的告警信息。由于客户没有专职的安全人员&#xff0c;由运维人员兼任安全运营工作&#xff…

OA项目值用户登入首页展示

1.什么是OA 办公自动化(Office Automation,简称OA)是将现代化办公和计算机技术结合起来的一种新型的办公方式。办公自动化没有统一的定义,凡是在传统的办公室中采用各种新技术、新机器、新设备从事办公业务,都属于办公自动化的领域。通过实现办公自动化,或者说实现数字化…

微信小程序开发——比较两个数字大小

在这里我们使用的工具是 需要自行安装和配置。 在微信小程序中比较两个数字大小有以下几种方式&#xff1a; 一、普通条件判断 在小程序的.js 文件中&#xff0c;先定义两个数字&#xff0c;如let num1 5; let num2 3;。通过if - else if - else语句&#xff0c;根据num1与…

在VB.net中,DateTime类使用,举例说明

标题 在VB.net中&#xff0c;DateTime类使用&#xff0c;举例说明 前面学习相关 1.在VB.net中&#xff0c;如何把"20240906"转化成日期格式 2.在VB.net中 DateTime有什么属性与方法 3.在VB.net中&#xff0c;Stopwatch有什么属性与方法 正文 在VB.NET中&#xff0c;D…

vite + vue3 + ts 移动端开箱即用现代开发模板

中文 | English SouthernWind https://blog.csdn.net/nanchen_J?typeblog sw-template vite vue3 ts 移动端开箱即用现代开发模板 特点 &#x1f436; Vite 的Vue3 的文件路由布局系统Mock 后续支持Api 自动引入组件自动引入VueUse 支持TypeScript 的Tailwind css 的暗…

优化算法(二)—粒子群优化算法(附MATLAB程序)

粒子群优化算法&#xff08;Particle Swarm Optimization, PSO&#xff09;是一种基于群体智能的优化算法&#xff0c;由James Kennedy和Russ Eberhart于1995年提出。它模仿鸟群觅食的行为&#xff0c;利用一组“粒子”在搜索空间中进行探索&#xff0c;以寻找最优解。每个粒子…

AI大模型知识点大梳理_ai大模型知识学习,零基础入门到精通,收藏这一篇就够了

文章目录 AI大模型是什么AI大模型发展历程AI大模型的底层原理AI大模型解决的问题大模型的优点和不足影响个人观点 AI大模型是什么 AI大模型是指具有巨大参数量的深度学习模型&#xff0c;通常包含数十亿甚至数万亿个参数。这些模型可以通过学习大量的数据来提高预测能力&…

尝试解决ubuntu中安装应用时出现依赖不满足的问题

在ubuntu或者其他linux环境中安装应用时&#xff0c;我们有时候会遇到以来不满足的问题&#xff0c;这时候就会导致目标应用无法被安装&#xff0c;比如&#xff1a; 怎么办呢&#xff1f; 第一种方式&#xff1a; 首先&#xff0c;尝试更新软件库。 先后执行以下两个命令 sudo…

输电线路在线监测摄像头:规格(一)

输电线路在线监测摄像头&#xff1a;规格&#xff08;一&#xff09; 1、设备具备前视高清变焦镜头&#xff0c;后视日夜一体高清镜头&#xff0c;整机一体化设计&#xff0c;不拆分。 2、采用工业级高清摄像头&#xff0c;像素≥1600万&#xff0c;可按现场需求设置。 3、支持…

【机器学习】--- 生成对抗网络 (GANs)

生成对抗网络 (GANs) —— 机器学习中的一个热点 生成对抗网络&#xff08;GANs, Generative Adversarial Networks&#xff09;近年来在机器学习领域成为一个热点话题。自从Ian Goodfellow及其团队在2014年提出这一模型架构以来&#xff0c;GANs 在图像生成、数据增强、风格转…

duilib 直接可编译运行的 实例DEMO

陆陆续续花时间精力做了几个DEMO,VS2013以上,编译即可运行,资源样式都带着。如果学习使用,或类似需求的话,可以参考下,有需要的,可以私信联系。 目录 1、duiliib 基本控件使用示例 2、文件选择对话框 3、登录界面例子 4、各种消息框的示例 5、时间工具条示例 6、透…

Web大学生网页作业成品——在线购物商城网页设计与实现(HTML+CSS+JS)(4个页面)

&#x1f389;&#x1f389;&#x1f389; 常见网页设计作业题材有**汽车、环保、明星、文化、国家、抗疫、景点、人物、体育、植物、公益、图书、节日、游戏、商城、旅游、家乡、学校、电影、动漫、非遗、动物、个人、企业、美食、婚纱、其他**等网页设计题目, 可满足大学生网…

重塑在线软件开发新纪元:集成高效安全特性,深度解析与评估支持浏览器在线编程的系统架构设计

目录 案例 【题目】 【问题 1】(13 分) 【问题 2】(12 分) 【答案】 【问题 1】解析 【问题 2】解析 相关推荐 案例 阅读以下关于软件架构设计与评估的叙述&#xff0c;回答问题1和问题2。 【题目】 某公司拟开发一套在线软件开发系统&#xff0c;支持用户通过浏览器…

Qt_自定义信号

目录 1、自定义信号的规定 2、创建自定义信号 3、带参数的信号与槽 4、一个信号连接多个槽 5、信号与槽的断开 结语 前言&#xff1a; 虽然Qt已经内置了大量的信号&#xff0c;并且这些信号能够满足大部分的开发场景&#xff0c;但是Qt仍然允许开发者自定义信号&#…

【Unity精品插件】NGUI:UI设计传奇工具

&#x1f4c2; Unity 开发资源汇总 | 插件 | 模型 | 源码 &#x1f493; 欢迎访问 Unity 打怪升级大本营 在Unity3D的世界中&#xff0c;用户界面&#xff08;UI&#xff09;是玩家与游戏互动的重要桥梁。随着游戏和应用的复杂性不断增加&#xff0c;传统的UI解决方案已经难以满…