重学SpringBoot3-内容协商机制

重学SpringBoot3-内容协商机制

  • ContentNegotiationConfigurer接口
  • 配置内容协商
    • URL参数
    • Accept头
    • 使用Url扩展名
  • 自定义内容协商格式
    • 步骤1: 注册自定义媒体类型
    • 步骤2: 实现`HttpMessageConverter`接口
    • 步骤3: 使用自定义`HttpMessageConverter`
  • 注意点

在 Spring Boot 3 中,内容协商(Content Negotiation)是一个非常重要的概念,特别是在构建 RESTful API 时。内容协商机制允许客户端和服务器就如何交换资源的数据格式达成协议。简单来说,它允许客户端通过请求头指定它们希望接收响应的格式(如 JSON,XML 等),服务器基于这些信息来决定以什么格式返回数据。

ContentNegotiationConfigurer接口

org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer

ContentNegotiationConfigurer 是 Spring 框架中的一个接口,用于自定义内容协商策略,主要通过以下几种方式来实现:

  1. URL参数: 通过 URL 参数来指定响应格式,例如,?format=json
  2. Accept头: 通过 Accept 请求头来指定希望接收的响应类型,这是HTTP规范推荐的方式。
  3. 扩展名: 通过 URL 的扩展名来指定响应的格式。例如,.json 表示希望响应为 JSON 格式,.xml 表示希望响应为 XML 格式。

配置内容协商

在 Spring Boot 3 中,你可以在 application.propertiesapplication.yml 文件中进行基本的内容协商配置:

# 开启基于请求参数的内容协商功能,默认此功能不开启
spring.mvc.contentnegotiation.favor-parameter=true
# 指定内容协商时使用的参数名。默认是 format
spring.mvc.contentnegotiation.parameter-name=mediaType
# 用于设置支持的内容协商(Content Negotiation)的媒体类型
spring.mvc.contentnegotiation.media-types.json=application/json
spring.mvc.contentnegotiation.media-types.xml=application/xml

或者通过配置类来实现更复杂的逻辑,没错,就是之前讲过的通过重新 WebMvcConfigurer 接口方法实现自定义配置:

public interface WebMvcConfigurer {default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {}// 其他方法
}

以下是一个示例,演示如何通过配置类来配置内容协商策略:

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void configureContentNegotiation(ContentNegotiationConfigurer configurer) {configurer.favorParameter(true).parameterName("mediaType").ignoreAcceptHeader(false).useRegisteredExtensionsOnly(false).defaultContentType(MediaType.APPLICATION_JSON).mediaType("json", MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML);}
}

在这个配置中:

  • favorParameter(true):允许使用 URL 参数进行内容协商。
  • parameterName("mediaType"):指定 URL 参数的名称。
  • ignoreAcceptHeader(false):不忽略 Accept 头,即同时支持Accept头和URL参数。
  • useRegisteredExtensionsOnly(false):不仅仅基于已注册的扩展进行格式匹配。
  • defaultContentType(MediaType.APPLICATION_JSON):设置默认的响应类型为JSON。
  • mediaType("json", MediaType.APPLICATION_JSON)mediaType("xml", MediaType.APPLICATION_XML):注册 URL 扩展名到 MIME 类型的映射。

注意,如果要支持输出 XML 需要 pom 文件引入 jackson 包:

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

controller代码

URL参数

需要携带查询字符串 ?mediaType=

json格式

xml格式

Accept头

修改请求头使用 postman 或者 apifox 工具。

json格式

xml格式

使用Url扩展名

从Spring Framework 5.3开始,官方推荐使用其他内容协商机制(如请求头Accept)而非扩展名,因为路径扩展可能会引起一些安全和使用上的问题。因此,在实际应用中,建议评估使用扩展名方式的必要性。

配置了基于扩展名的内容协商,配置文件已经不支持这种配置,所有改成新建配置类的方式:

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void configureContentNegotiation(ContentNegotiationConfigurer configurer) {configurer.favorPathExtension(true).favorParameter(false).ignoreAcceptHeader(false).useRegisteredExtensionsOnly(true).mediaType("json", MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML);}
}

配置

json格式

xml格式

自定义内容协商格式

自定义内容协商格式主要涉及到两个方面:一是自定义支持的媒体类型(Media Types),二是自定义对这些媒体类型的处理。

在 Spring Boot 3 中,自定义内容协商格式通常需要以下几个步骤:

  1. 注册自定义媒体类型:你可以通过配置类来注册自定义的媒体类型,让 Spring MVC 知道你打算支持哪些额外的格式。
  2. 实现 HttpMessageConverter 接口:对于每种你想支持的媒体类型,你需要提供一个相应的HttpMessageConverter实现,用于序列化和反序列化数据。
  3. 配置 Spring MVC 以使用你的自定义 HttpMessageConverter:最后,你需要在 Spring MVC 配置中注册你的 HttpMessageConverter 实现,以确保Spring MVC 会使用它们进行请求和响应的处理。

步骤1: 注册自定义媒体类型

假设你想添加对 application/yaml 这种媒体类型的支持,首先需要在配置类中注册这种媒体类型:

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void configureContentNegotiation(ContentNegotiationConfigurer configurer) {configurer.mediaType("yaml", MediaType.valueOf("application/x-yaml"));}
}

或者使用配置文件:

spring.mvc.contentnegotiation.media-types.yaml=application/x-yaml

还需要引入 Jackson 库的 YAML 数据格式支持:

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

步骤2: 实现HttpMessageConverter接口

接下来,需要创建一个 HttpMessageConverter 实现,用于处理 YAML 格式的数据。这里需要实现 readwrite 方法,分别用于反序列化和序列化数据。例如,使用 YamlMapper(这是一个假设的类,实际上你可能需要使用例如SnakeYAML之类的库):

package com.coderjia.springboot304web.config;import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;import java.io.IOException;/*** @author CoderJia* @create 2024/3/9 下午 10:32* @Description**/
public class YamlHttpMessageConverter extends AbstractHttpMessageConverter<Object> {private final YAMLMapper yamlMapper = new YAMLMapper();public YamlHttpMessageConverter() {super(MediaType.valueOf("application/x-yaml"));}@Overrideprotected boolean supports(Class<?> clazz) {// 这里简化了实现,实际上你可能需要更复杂的逻辑来决定你的converter支持哪些类return true;}@Overrideprotected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {// 从HttpInputMessage中读取并解析YAML格式的数据return yamlMapper.readValue(inputMessage.getBody(), clazz);}@Overrideprotected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {// 将给定的对象写入HttpOutputMessage的body中yamlMapper.writeValue(outputMessage.getBody(), object);}
}

步骤3: 使用自定义HttpMessageConverter

最后,需要在 Spring MVC 配置中注册这个新的 HttpMessageConverter。这通常是在一个配置类中完成,通过重写 configureMessageConverters方法:

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void configureContentNegotiation(ContentNegotiationConfigurer configurer) {configurer.mediaType("yaml", MediaType.valueOf("application/x-yaml"));}@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {converters.add(new YamlHttpMessageConverter());}}

这样,当客户端请求以 application/x-yaml 格式接收数据时(比如,通过设置Accept: application/x-yaml头),Spring MVC 就会使用你的 YamlHttpMessageConverter 来序列化响应数据为YAML格式:

yaml格式

注意点

内容协商的配置和实现方式可能因 Spring Boot 版本的不同而略有变化。上述示例适用于 Spring Boot 3,但在实际应用中,还需要根据具体的需求和环境来调整配置。

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

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

相关文章

linux系统Docker容器Dockerfile示例

Dockerfile示例 可以使用systemctl命令的镜像Dockerfile 基于centos7创建mysql镜像Dockerfilemysql.sh 可以使用systemctl命令的镜像 Dockerfile vim DockerfileFROM centos:7 ENV container dockerRUN yum -y swap -- remove fakesystemd -- install systemd systemd-libs R…

SQL中如何添加数据:基础指南

在数据库管理系统中&#xff0c;添加数据是一项常见的任务。无论是向现有表中添加新行&#xff0c;还是创建新表并插入数据&#xff0c;都需要使用SQL&#xff08;Structured Query Language&#xff09;语句来执行。本文将介绍SQL中如何添加数据的基本方法&#xff0c;以及一些…

vue学习笔记21-组件传递数据_Props

组件与组件之间不是完全独立的&#xff0c;而是有交集的&#xff0c;那就是组件与组件之间是可以传递数据的 传递数据的解决方案就是props 父级&#xff1a; 在父级中引入子集 <template><h3>Parent</h3><Child/> </template><script> i…

PyCaret(Python自动化机器学习)自定义交互式解释性模型

要点 PyCaret代码实现数学定义分类、聚类、异常检测和自然语言处理模型PyCaret模型创建模型和数据分析&#xff1a;身体质量指数回归模型探索性数据分析&#xff0c;植物物种分类模型预测&#xff0c;合成数据聚类模型探索性数据分析&#xff0c;批发商客户异常检测模型探索性…

GFP-GAN环境搭建推理测试

引子 近期&#xff0c;文生图&#xff0c;wav2lip很火&#xff0c;文生图&#xff0c;见识的太多&#xff0c;不多说了。wav2lip其通过语音驱动唇部动作并对视频质量进行修复&#xff0c;里面一般涉及到三个步骤&#xff0c;文本到语音转化&#xff0c;语音驱动唇部动作&#…

YOLOv9/YOLOv8算法改进【NO.103】引入YOLOv9提出模块RepNCSPELAN模块,亲测有效

前 言 YOLO算法改进系列出到这,很多朋友问改进如何选择是最佳的,下面我就根据个人多年的写作发文章以及指导发文章的经验来看,按照优先顺序进行排序讲解YOLO算法改进方法的顺序选择。具体有需求的同学可以私信我沟通: 首推,是将两种最新推出算法的模块进行融合形成…

【C++初阶】第五站:C/C++内存管理 (匹配使用,干货到位)

前言&#xff1a; 本文知识点&#xff1a; 1. C/C内存分布2. C语言中动态内存管理方式3. C中动态内存管理4. operator new与operator delete函数 5. new和delete的实现原理 &#xff08;干货在此&#xff09; 6. 定位new表达式(placement-new)7. 常见面试题 目录 C/C内…

Linux操作系统内核参数调优-2

1. 请解释Linux内核参数调优的目的和重要性。 Linux内核参数调优的目的主要是提高系统性能、稳定性和安全性。它的重要性体现在以下几个方面&#xff1a; 提升系统性能&#xff1a;通过调整内核参数&#xff0c;可以使系统更高效地利用硬件资源&#xff0c;例如CPU、内存和I/…

Java反射、枚举类和lambda表达式

前言&#xff1a; 本章我们就来了解Java中的反射和枚举类。枚举类和反射其实有些关系&#xff0c;接下来我们就来学习他们的使用。 反射&#xff1a; 反射的作用&#xff1a; 反射&#xff1a;反射允许对成员变量&#xff0c;成员方法和构造方法的信息进行编程访问。 Java中有…

CVE-2021-31440:eBPF verifier __reg_combine_64_into_32 边界更新错误

文章目录 前言漏洞分析构造 vuln reg 漏洞利用漏洞修复参考 前言 影响版本&#xff1a;Linux 5.7 ~ 5.11.20 8.8 编译选项&#xff1a;CONFIG_BPF_SYSCALL&#xff0c;config 所有带 BPF 字样的编译选项。General setup —> Choose SLAB allocator (SLUB (Unqueued Allocat…

从0到1手把手实现RPC|01 RpcProvider本地实现

RPC的简化版原理如下图&#xff08;核心是代理机制&#xff09;。 1.本地代理存根: Stub2.本地序列化反序列化3.网络通信4.远程序列化反序列化5.远程服务存根: Skeleton6.调用实际业务服务7.原路返回服务结果8.返回给本地调用方 注意处理异常。 RpcProvider的本地实现 1、工…

xss.haozi.me靶机 通关

0x00 没有任何过滤可以直接注入<img srcx οnerrοralert(1)> 0x01 使用了testarea标签将我们的输入内容以普通的字符串进行展示 但是我们可以将标签进行闭合 </textarea><img srcx οnerrοralert(1)> 0x02 我们依然可以先闭合之后添加属性a" οncl…

word[::-1] for word in s.split()得到的是一个列表

你可以将上述的列表推导式代码拆分为更明确的几个步骤&#xff0c;如下所示&#xff1a; # 原始字符串 s "hello world" # 使用 split() 方法将字符串分割成单词列表 words s.split() # 创建一个空列表&#xff0c;用于存储反转后的单词 reversed_words [] # 遍历…

npm与Maven:前端与后端构建工具深度对比学习

文章目录 npm与Maven&#xff1a;前端与后端构建工具深度对比学习引言一、基础概念与起源1.1 npm简介&#xff1a;定义与在Node.js生态中的角色及其发展历程1.2 Maven简介&#xff1a;设计理念“约定优于配置”及在Java生态系统中的地位与应用范围二、核心功能对比分析2.1 依赖…

对于两个独立随机变量X,Y, E(XY)=E(X)E(Y)

两个独立随机变量X&#xff0c;Y的期望分别是E(X), E(Y), 其乘积XY的期望是多少&#xff1f; 我们可以利用期望的性质来求得XY的期望。由于X、Y是独立随机变量&#xff0c;因此它们的协方差为0&#xff0c;即&#xff1a; cov(X, Y) E(XY) - E(X)E(Y) 0 因此&#xff0c; …

Java17 --- SpringCloud之Consul

目录 一、consul的使用 1.1、主要功能 1.2、安装及运行 1.3、添加微服务到consul 1.3.1、8001微服务添加相关pom、配置文件、注解 1.3.2、80微服务添加相关pom、配置文件、注解 1.4、三个注册中心异同 1.5、consul进行分布式配置 1.5.1、修改8001的yml配置文件 1.5.2…

数字化运营在教育行业的技术架构实践总结

随着科技的不断进步和数字化时代的到来&#xff0c;教育行业也正面临着数字化转型的挑战和机遇。教育行业的数字化运营需要依靠合理的技术架构来支撑&#xff0c;本文将探讨教育行业数字化运营的技术架构设计。 ## 第一步&#xff1a;需求分析和架构设计 在构建教育行业数字化…

SpringMVC08、Json

8、Json 8.1、什么是JSON&#xff1f; JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式&#xff0c;目前使用特别广泛。采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。易于人阅读和…

Windows更改MySQL-8的数据库数据存放位置

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、为什么要用8.x版本&#xff1f;二、为什么要更改存放位置三、开始操作1.断开Client并关闭Server2.找到Data目录3.创建备份目录4.更改配置文件5.更改注册表6…

华为OD面试分享13(2024年)

华为OD面经 二战失败选手,双非一本部门目标院校,数学与应用数学专业,无相关工作经验也没有什么拿得出手的项目。3月中旬开始重新学java(大学里有学过一个学期的java,很水)。期间经常通宵肝,学习框架、刷leedcode,可能是因为数学专业出身,数据结构和算法这一块学起来并…