JAVA:利用 Content Negotiation 实现多样式响应格式的技术指南
1、简述
Content Negotiation(内容协商) 是 RESTful 服务的重要特性,允许客户端和服务器根据请求的不同特性动态选择适合的响应格式。它是一种在 HTTP 协议中实现的机制,通过它,服务器能够根据客户端需求返回适合的内容类型(如 JSON、XML、HTML)。
本文将介绍 Content Negotiation 的原理、实现方式,并通过详细示例演示其在 Spring Boot 中的实际应用。
2、原理
Content Negotiation 的核心在于客户端通过 HTTP 请求头中的 Accept、Content-Type 等字段,告知服务器它支持的内容格式,而服务器根据这些信息返回匹配的内容。以下是主要的 HTTP 头字段:
- Accept:指定客户端希望接受的内容类型。例如:
Accept: application/json
表示客户端希望接收到 JSON 格式的响应。
-
Content-Type:指定请求体的内容格式(如 POST 请求的 JSON 数据)。
-
Accept-Language:指定客户端支持的语言。
Content Negotiation 有以下三种常见实现方式:
-
HTTP Header-Based Negotiation(基于请求头的协商)
客户端通过 Accept 头告知服务器期望的响应类型。
示例:Accept: application/xml。 -
URL Path-Based Negotiation(基于 URL 路径的协商)
通过扩展名直接指定期望的响应类型。
示例:/api/resource.json。 -
Query Parameter-Based Negotiation(基于查询参数的协商)
客户端通过查询参数指定期望的响应类型。
示例:/api/resource?format=json。
3、Content Negotiation 实现
Spring Boot 提供了对 Content Negotiation 的内置支持,可以轻松实现多种响应格式。
3.1 添加必要的依赖
确保你的项目中已经包含以下依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId>
</dependency>
3.2 配置 Content Negotiation
在 Spring Boot 中,通过 ContentNegotiationConfigurer 配置支持的内容协商方式:
package com.example.springbootclient.config;import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void configureContentNegotiation(ContentNegotiationConfigurer configurer) {configurer// 支持 URL 后缀形式,如 .json 或 .xml.favorPathExtension(true)// 支持查询参数,如 ?format=json 或 ?format=xml.favorParameter(true).parameterName("format")// 如果未指定,则根据请求头返回内容类型.ignoreAcceptHeader(false).useRegisteredExtensionsOnly(false)// 默认返回 JSON.defaultContentType(MediaType.APPLICATION_JSON)// 注册媒体类型.mediaType("json", MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML);}
}
3.3 创建示例控制器
创建一个简单的 REST 控制器,用于返回多种格式的数据:
package com.example.springbootclient.controller;import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/api")
public class ContentNegotiationController {@GetMapping(value = "/resource")public ResponseEntity<Object> getResource() {Map<String, String> data = new HashMap<>();data.put("id", "1");data.put("name", "Content Negotiation Example");return ResponseEntity.ok(data);}@GetMapping(value = "/resource.{format}", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})public ResponseEntity<Object> getFormat() {Map<String, String> data = new HashMap<>();data.put("id", "1");data.put("name", "Content Negotiation Example");return ResponseEntity.ok(data);}
}
4、详细样例
以下是几种 Content Negotiation 的请求和响应示例:
4.1 基于 HTTP 请求头
请求:
GET /api/resource HTTP/1.1
Host: localhost:8080
Accept: application/json
响应:
{"id": "1","name": "Content Negotiation Example"
}
如果请求头为 Accept: application/xml,响应为:
<HashMap><name>Content Negotiation Example</name><id>1</id>
</HashMap>
4.2 基于 URL 路径扩展名
请求:
GET /api/resource.json HTTP/1.1
Host: localhost:8080
响应:
{"id": "1","name": "Content Negotiation Example"
}
请求:
GET /api/resource.xml HTTP/1.1
Host: localhost:8080
响应:
<HashMap><name>Content Negotiation Example</name><id>1</id>
</HashMap>
4.3 基于查询参数
请求:
GET /api/resource?format=json HTTP/1.1
Host: localhost:8080
响应:
{"id": "1","name": "Content Negotiation Example"
}
请求:
GET /api/resource?format=xml HTTP/1.1
Host: localhost:8080
响应:
<HashMap><name>Content Negotiation Example</name><id>1</id>
</HashMap>
5、Content Negotiation 的优缺点
5.1 优点:
- 客户端可以灵活选择所需的内容格式。
- 支持多种协商方式,适用性广。
- 降低了为不同格式创建独立 API 的复杂性。
5.2 缺点:
- 配置较为复杂,可能导致意外的行为。
- 扩展名协商可能不符合 RESTful API 的最佳实践。
- 对 Accept 头的支持可能不一致。
6、总结
Content Negotiation 是 RESTful API 中的重要功能,能够为客户端提供更好的灵活性。在 Spring Boot 中,Content Negotiation 的实现非常灵活,支持多种协商方式。通过合理的配置和设计,可以实现更加优雅和高效的服务接口。希望本文对你理解 Content Negotiation 的核心原理和实现有所帮助!
相关文章:

JAVA:利用 Content Negotiation 实现多样式响应格式的技术指南
1、简述 Content Negotiation(内容协商) 是 RESTful 服务的重要特性,允许客户端和服务器根据请求的不同特性动态选择适合的响应格式。它是一种在 HTTP 协议中实现的机制,通过它,服务器能够根据客户端需求返回适合的内…...
layui Table单元格编辑支持Enter键换行,包括下拉框单元格
layui Table表格编辑支持Enter键换行 可编辑单元格 $(".layui-table td").keydown(function (e) {// console.log("111",e);var index $(this).index(),tr $(this).parent(tr),isKeydown (event.type "keydown");if (e.code "Enter&q…...
Swoole的MySQL连接池实现
在Swoole中实现MySQL连接池可以提高数据库连接的复用率,减少频繁创建和销毁连接所带来的开销。以下是一个简单的Swoole MySQL连接池的实现示例: 首先,确保你已经安装了Swoole扩展和PDO_MySQL扩展(或mysqli,但在这个示…...

无人机红外热成像:应急消防的“透视眼”
无人机红外热成像:应急消防的“透视眼” 亲爱的小伙伴们,每年一到夏天,应急消防的战士们就像上紧了发条的闹钟,时刻准备应对各种灾害。炎热天气让火灾隐患“蹭蹭”往上涨,南北各地还有防洪救灾、台风、泥石流等灾害轮…...
【redis】Redis操作String类型key的发生了什么?
关于Redis操作(添加、删除、修改、查询)String类型key的完整过程,包括引用源码数据、时序图、磁盘IO读写、数据长度限制和故障处理机制。 数据结构 Redis对象(robj) typedef struct redisObject {unsigned type:4; …...

hdfs之读写流程
写入流程: 客户端Client想将文件a.txt上传至hdfs,首先向Namenode发送请求进行权限校验,Namenode通过后会计算出来三个节点,并将这三个节点告知客户端,客户端将输入进行切割成块,一个一个的块进行传输&…...

研发的立足之本到底是啥?
0 你的问题,我知道! 本文深入T型图“竖线”的立足之本:专业技术 技术赋能业务能力。研发在学习投入精力最多,也误区最多。 某粉丝感发展遇到瓶颈,项目都会做,但觉无提升,想跳槽。于是&#x…...

Baklib揭示内容中台与人工智能技术的创新协同效应
内容概要 在当今信息爆炸的时代,内容的高效生产与分发已成为各行业竞争的关键。内容中台与人工智能技术的结合,为企业提供了一种新颖的解决方案,使得内容创造的流程更加智能化和高效化。 内容中台作为信息流动的核心,能够集中管…...

智慧消防营区一体化安全管控 2024 年度深度剖析与展望
在 2024 年,智慧消防营区一体化安全管控领域取得了令人瞩目的进展,成为保障营区安全稳定运行的关键力量。这一年,行业在政策驱动、技术创新应用、实践成果及合作交流等方面呈现出多元且深刻的发展态势,同时也面临着一系列亟待解决…...
自定义数据集,使用 PyTorch 框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测
在本文中,我们将展示如何使用 NumPy 创建自定义数据集,利用 PyTorch 实现一个简单的逻辑回归模型,并在训练完成后保存该模型,最后加载模型并用它进行预测。 1. 创建自定义数据集 首先,我们使用 NumPy 创建一个简单的…...
UE5 特效
能帮到你的话,就给个赞吧 😘 文章目录 post processexposurebloomvignettesaturationunbound material材质蓝图alt z base colorconstant3Vector roughnessconstant metallicconstant pbrroughnessmetallicmake more realmake some areas rougher than o…...
CMAKE工程编译好后自动把可执行文件传输到远程开发板
# 设置 CMake 最低版本要求 cmake_minimum_required(VERSION 3.10)# 设置项目名称 project(MyProject)# 添加可执行文件,这里以项目名作为可执行文件的名称 add_executable(${PROJECT_NAME} main.cpp)# 设置开发板信息 set(DEVELOPMENT_BOARD_IP "192.168.1.10…...

Windows 程序设计7:文件的创建、打开与关闭
文章目录 前言一、文件的创建与打开CreateFile1. 创建新的空白文件2. 打开已存在文件3. 打开一个文件时,如果文件存在则打开,如果文件不存在则新创建文件4.打开一个文件,如果文件存在则打开文件并清空内容,文件不存在则 新创建文件…...
策略模式 - 策略模式的使用
引言 在软件开发中,设计模式是解决常见问题的经典解决方案。策略模式(Strategy Pattern)是行为型设计模式之一,它允许在运行时选择算法的行为。通过将算法封装在独立的类中,策略模式使得算法可以独立于使用它的客户端…...

具身智能研究报告
参考: (1)GTC大会&Figure:“具身智能”奇点已至 (2)2024中国具身智能创投报告 (3)2024年具身智能产业发展研究报告 (4)具身智能行业深度:发展…...

Windows安装Milvus
安装Milvus 安装Docker前置条件: 安装Mlivus方案一方案二 Attu管理端 安装Docker 系统:Windows 11 家庭中文版 Mlivus:V2.3.0 Attu: V2.3.10 前置条件: 启用“适用于 Linux 的 Windows 子系统”可选功能,才能在 Win…...

Excel分区间统计分析(等步长、不等步长、多维度)
在数据分析过程中,可能会需要统计不同数据区间的人数、某个数据区间的平均值或者进行分组区间统计,本文从excel函数到数据透视表的方法,从简单需求到复杂需求,采用不同的方法进行讲解,尤其是通过数据透视表的强大功能大…...

宝塔mysql数据库容量限制_宝塔数据库mysql-bin.000001占用磁盘空间过大
磁盘空间占用过多,排查后发现网站/www/wwwroot只占用7G,/www/server占用却高达8G,再深入排查发现/www/server/data目录下的mysql-bin.000001和mysql-bin.000002两个日志文件占去了1.5G空间。 百度后学到以下知识,做个记录。 mysql…...
LeetCode 2412.完成所有交易的初始最少钱数:【年度巨献】举例说明(讲明白),由难至简(手脚不乱),附Python一行版
【LetMeFly】2412.完成所有交易的初始最少钱数:【年度巨献】举例说明(讲明白),由难至简(手脚不乱),附Python一行版 文章目录 【LetMeFly】2412.完成所有交易的初始最少钱数:【年度巨献】举例说明(讲明白),由难至简(手脚…...

多人-多agent协同可能会挑战维纳的反馈
在多人-多Agent协同系统中,维纳的经典反馈机制将面临新的挑战,而协同过程中的“算计”(策略性决策与协调)成为实现高效协作的核心。 1、非线性与动态性 维纳的反馈理论(尤其是在控制理论中)通常假设系统的动…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果:邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...

算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...