spring mvc @ResponseBody 注解转换为 JSON 的原理与实现详解

@ResponseBody 注解转换为 JSON 的原理与实现详解
1. 核心作用
@ResponseBody 是 Spring MVC 的一个注解,用于将方法返回的对象直接序列化为 HTTP 响应体(如 JSON 或 XML),而不是通过视图解析器渲染为视图(如 HTML)。
- 关键作用:
- 跳过视图解析阶段,直接返回数据。
- 触发 消息转换器(HttpMessageConverter) 将对象转换为指定格式(如 JSON)。
2. 工作流程详解
步骤 1:方法返回对象
@RestController
public class UserController {@GetMapping("/user")public User getUser() {return new User("John", 25); // 返回 Java 对象}
}
步骤 2:触发消息转换
- Spring 检测到
@ResponseBody:跳过视图解析,直接进入消息转换阶段。 - 选择合适的
HttpMessageConverter:- 根据 返回对象类型 和 请求的 Accept 头(如
application/json)选择转换器。 - 默认情况下,Spring Boot 自带的 Jackson 库 提供的
MappingJackson2HttpMessageConverter会被选中。
- 根据 返回对象类型 和 请求的 Accept 头(如
步骤 3:Jackson 序列化对象
- Jackson 的
ObjectMapper:负责将 Java 对象转换为 JSON 字符串。 - 序列化过程:
- 遍历对象的 getter 方法 或 字段。
- 根据注解(如
@JsonProperty)和配置(如日期格式)处理属性。 - 忽略
transient字段或@JsonIgnore标记的字段。
// 示例 JSON 输出
{"name": "John","age": 25
}
3. 完整代码示例
3.1 实体类(User.java)
public class User {private String name;private int age;// 构造函数、getter 和 setter 方法public User(String name, int age) {this.name = name;this.age = age;}// 省略 getter/setter
}
3.2 控制器(UserController.java)
import org.springframework.web.bind.annotation.*;@RestController // 等效于 @Controller + @ResponseBody
public class UserController {@GetMapping("/user")public User getUser() {return new User("John", 25); // 直接返回对象,由 @ResponseBody 触发转换}@PostMapping("/user")public User createUser(@RequestBody User user) {// 处理 POST 请求,将 JSON 反序列化为 User 对象return user;}
}
3.3 测试请求
# GET 请求获取 JSON
curl http://localhost:8080/user
# 输出:{"name":"John","age":25}# POST 请求发送 JSON
curl -X POST -H "Content-Type: application/json" -d '{"name":"Jane","age":30}' http://localhost:8080/user
4. 消息转换器(HttpMessageConverter)详解
Spring MVC 通过 HttpMessageConverter 完成对象到 HTTP 响应的转换。
-
核心接口:
HttpMessageConverter<T>canRead():判断是否支持反序列化(如 JSON → 对象)。canWrite():判断是否支持序列化(如对象 → JSON)。write():实际执行序列化操作。
-
常用实现类:
类名 作用 默认支持格式 MappingJackson2HttpMessageConverterJSON 转换(依赖 Jackson 库) application/jsonMappingJackson2XmlHttpMessageConverterXML 转换(需额外配置) application/xmlStringHttpMessageConverter字符串转换 text/plain
5. Jackson 配置与自定义
通过自定义 ObjectMapper 可控制 JSON 序列化行为:
5.1 配置示例
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.text.SimpleDateFormat;@Configuration
public class JacksonConfig {@Beanpublic ObjectMapper objectMapper() {ObjectMapper mapper = new ObjectMapper();// 设置日期格式mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));// 忽略未找到的字段(反序列化时)mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);return mapper;}
}
5.2 常用注解
| 注解 | 作用 |
|---|---|
@JsonProperty | 指定 JSON 键名(覆盖字段名)。 |
@JsonFormat | 定制日期/数字格式。 |
@JsonInclude | 控制字段是否参与序列化(如 @JsonInclude(JsonInclude.Include.NON_NULL))。 |
@JsonIgnore | 忽略字段。 |
6. 常见问题与解决方案
Q1:为什么 JSON 中没有某个字段?
- 可能原因:
- 字段没有
getter方法。 - 字段被
@JsonIgnore或transient修饰。 @JsonInclude配置排除了该字段(如NON_NULL且值为null)。
- 字段没有
Q2:如何处理循环引用?
- 解决方案:
@JsonManagedReference // 主对象(单向引用) @JsonBackReference // 被引用对象(忽略反向引用)
Q3:如何自定义序列化逻辑?
- 自定义序列化器:
public class CustomSerializer extends JsonSerializer<Date> {@Overridepublic void serialize(Date value, JsonGenerator gen, SerializerProvider serializers)throws IOException {gen.writeString(new SimpleDateFormat("yyyy-MM-dd").format(value));} }
Q4:如何禁用 HTML 转义?
- 配置:
@Bean public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() {MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();converter.getObjectMapper().disable(SerializationFeature.ESCAPE_NON_ASCII);return converter; }
7. 总结表格
| 环节 | 关键组件 | 职责 |
|---|---|---|
| 触发转换 | @ResponseBody | 告知 Spring 直接返回数据,跳过视图解析。 |
| 选择转换器 | HttpMessageConverter | 根据返回类型和 Accept 头选择合适的转换器。 |
| 序列化 | Jackson(ObjectMapper) | 将 Java 对象转换为 JSON 字符串。 |
| 配置扩展 | 自定义 ObjectMapper | 精细控制序列化格式、日期、忽略策略等。 |
总结
@ResponseBody 通过结合 HttpMessageConverter 和 Jackson,将 Java 对象无缝转换为 JSON 响应。掌握其工作原理和配置方法,可以灵活处理 RESTful API 的数据格式化需求。对于复杂场景(如自定义序列化、处理循环引用),可通过 Jackson 的注解和配置进一步优化。
相关文章:
spring mvc @ResponseBody 注解转换为 JSON 的原理与实现详解
ResponseBody 注解转换为 JSON 的原理与实现详解 1. 核心作用 ResponseBody 是 Spring MVC 的一个注解,用于将方法返回的对象直接序列化为 HTTP 响应体(如 JSON 或 XML),而不是通过视图解析器渲染为视图(如 HTML&…...
TDengine.C/C++ 连接器
简介 C/C 开发人员可以使用 TDengine 的客户端驱动,即 C/C 连接器(以下都用 TDengine 客户端驱动表示),开发自己的应用来连接 TDengine 集群完成数据存储、查询以及其他功能。TDengine 客户端驱动的 API 类似于 MySQL 的 C API。…...
[docker] 简单操作场景
Docker的简单操作场景 1 安装 暂时没空写~ 2 登陆 一共4步: ~$ sudo docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d765d4c1eb5f ubuntu:24.04 "/bin/bash" …...
skynet.rawcall使用详解及应用场景
目录 核心特性函数原型使用场景场景 1:高性能二进制传输(如文件转发)场景 2:自定义序列化协议(如 Protocol Buffers)场景 3:跨服务共享内存(避免拷贝) 配套接收方实现与 …...
使用SpringSecurity下,发生重定向异常
使用SpringSecurity下,发生空转异常 环境信息: Spring Boot 3.4.4 , jdk 17 , springSecurity 6.4.4 问题背景: 没有自定义controller ,改写了login 页面,并且进行了成功后的跳转处理…...
gbase8s之逻辑导出导入脚本(完美版本)
该脚本dbexport.sh用于快速导出库和导入库(使用多并发unload,和多并发dbload的方式) #!/bin/sh #脚本功能:将数据导出成文本,迁移至其他实例 #最后更新时间:2023-12-19 #使用方法: #1.执行该脚…...
Elasticsearch | ES索引模板、索引和索引别名的创建与管理
关注:CodingTechWork 引言 在使用 Elasticsearch (ES) 和 Kibana 构建数据存储和分析系统时,索引模板、索引和索引别名的管理是关键步骤。本文将详细介绍如何通过 RESTful API 和 Kibana Dev Tools 创建索引模板、索引以及索引别名,并提供具…...
【Easylive】视频删除方法详解:重点分析异步线程池使用
【Easylive】项目常见问题解答(自用&持续更新中…) 汇总版 方法整体功能 这个deleteVideo方法是一个综合性的视频删除操作,主要完成以下功能: 权限验证:检查视频是否存在及用户是否有权限删除核心数据删除&…...
力扣hot100_回溯(2)_python版本
一、39. 组合总和(中等) 代码: class Solution:def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:ans []path []def dfs(i: int, left: int) -> None:if left 0:# 找到一个合法组合ans.append(pa…...
SGLang实战:从KV缓存复用到底层优化,解锁大模型高效推理的全栈方案
在当今快速发展的人工智能领域,大型语言模型(LLM)的应用已从简单对话扩展到需要复杂逻辑控制、多轮交互和结构化输出的高级任务。面对这一趋势,如何高效地微调并部署这些大模型成为开发者面临的核心挑战。本文将深入探讨SGLang——这一专为大模型设计的高…...
LPDDR4内存颗粒命名规则全解析:三星、镁光、海力士、南亚、长鑫等厂商型号解码与选型指南
由于之前DDR的系列选型文章有很好的反馈,所以补充LPDDR4低功耗内存的选型和命名规则,总结了目前市面上常用的内存,供硬件工程师及数码爱好者参考。 在智能手机、平板电脑和低功耗设备中,LPDDR4 SDRAM凭借其高带宽、低功耗特性成为…...
特权FPGA之Johnson移位
完整代码: module johnson(clk,rst_n,led,sw1_n,sw2_n,sw3_n);input clk; //时钟信号,50MHz input rst_n; //复位信号,低电平有效 output[3:0] led; //LED控制,1--灭…...
网络安全小知识课堂(最终完结版)
网络安全入门 :从 “小白” 到 “守护者” 的蜕变之旅 写在完结之际 历经 13 篇的深度探索,我们从 DDoS 攻击的 “流量洪水” 一路闯关到 HTTPS 的 “加密堡垒”,揭开了网络安全世界的层层面纱。感谢每一位读者的陪伴与互动,你们…...
2025年AI生成引擎搜索发展现状与趋势总结
2025年AI生成引擎搜索发展现状与趋势总结 一、国内外AI生成引擎搜索发展现状 1. 国内动态 社交搜索崛起:小红书2024年Q4日均搜索量达6亿次,用户更依赖社交平台UGC内容进行决策(如购物、旅游场景)&#…...
【杂谈】Godot4.4导出到Android平台(正式导出)
学博而后可约,事历而后知要。 目录 一、准备二、Gradle构建三、配置Java SDK四、配置Android SDK五、配置密钥 一、准备 本文在前文【杂谈】Godot4.4导出到安卓平台(调试导出)的基础上,进行正式导出。调试导出并不是真正的编译导…...
VBA将Word文档内容逐行写入Excel
如果你需要将Word文档的内容导入Excel工作表来进行数据加工,使用下面的代码可以实现: Sub ImportWordToExcel()Dim wordApp As Word.ApplicationDim wordDoc As Word.DocumentDim excelSheet As WorksheetDim filePath As VariantDim i As LongDim para…...
基于AI设计开发出来的业务系统是什么样的?没有菜单?没有表格?
基于AI设计开发出的业务系统仍然会包含菜单、表格等传统UI元素,但AI技术会显著改变它们的实现方式和交互逻辑。以下是具体分析: 一、传统元素的持续存在 功能刚需性 • 菜单承担着系统导航的核心功能,表格则是结构化数据展示的基础载体。根…...
C++ -异常之除以 0 问题(整数除以 0 编译时检测、整数除以 0 运行时检测、浮点数除以 0 编译时检测、浮点数除以 0 运行时检测)
一、整数除以 0(编译时检测) 1、演示 #include <iostream>using namespace std;int main() {int result 10 / 0;cout << result << endl;return 0; }程序无法运行,输出结果 error C2124: 被零除或对零求模2、演示解读 …...
数字足迹管理(DFM):你的网络隐身指南
数字足迹管理(DFM):你的网络隐身指南 你可能不知道,你的姓名、电话、住址正在网上被“明码标价” ——而这一切,可能只是因为你点过外卖、寄过快递,甚至注册过一个网站。 一、什么是数字足迹管理&#…...
如何避免“过度承诺”导致的验收失败
如何避免“过度承诺”导致的验收失败?关键在于: 评估可行性、设置合理目标、高频沟通反馈、阶段性验收、做好风险管理。其中设置合理目标至关重要,很多团队往往在项目初期为迎合客户或领导而报出“最理想方案”,忽略了资源、技术及…...
MySQL学习笔记集--游标
游标 在MySQL中,游标(Cursor)是一种数据库对象,它允许您逐行处理查询结果集。游标通常与存储过程一起使用,因为它们需要在存储过程或函数中声明和操作。游标的使用涉及几个步骤:声明游标、打开游标、从游标…...
紧跟数字人热潮:123 数字人分身克隆系统源码部署与风口洞察
在当今数字化浪潮中,数字人技术无疑已成为最具活力与潜力的领域之一,正以迅猛之势席卷多个行业,重塑着人们的交互方式与商业运作模式。C 站作为技术交流的前沿阵地,汇聚了众多关注前沿科技的开发者与技术爱好者,今天来…...
QT控件 修改QtTreePropertyBrowser自定义属性编辑器源码,添加第一列标题勾选,按钮,右键菜单事件等功能
头阵子遇到一个需要修改QtTreePropertyBrowser控件的需求,QT开发做这么久了,这个控件倒是第一次用,费了点时间研究,在这里做个简单的总结。 QtTreePropertyBrowser控件 是 Qt 解决方案 (Qt Solutions) 中的一个组件,用…...
Excel 日期值转换问题解析
目录 问题原因 解决方案 方法1:使用 DateTime.FromOADate 转换 方法2:处理可能为字符串的情况 方法3:使用 ExcelDataReader 时的处理 额外提示 当你在 Excel 单元格中看到 2024/12/1,但 C# 读取到 45627 时,这是…...
0. 七小时挑战:自研企业级任务调度器--前言
在软件开发的世界里,有一个亘古不变的问题:“为什么不直接用现成的?”这句话听起来合理、理性、务实,甚至有点老道。毕竟,时间宝贵、预算有限,轮子已经造好了,何必再动手? 但有时候…...
Spring 核心注解深度解析:@Autowired、@Repository 与它们的协作关系
引言 在 Spring 框架中,依赖注入(DI) 是实现松耦合架构的核心机制。Autowired 和 Repository 作为两个高频使用的注解,分别承担着 依赖装配 和 数据访问层标识 的关键职责。本文将深入探讨它们的功能特性、协作模式…...
开源模型应用落地-模型上下文协议(MCP)-从数据孤岛到万物互联(一)
一、前言 当开发者还在为每个AI工具编写臃肿的API适配器时,一场关于「连接」的技术革命已悄然降临。模型上下文协议(MCP)正在用一套全新的交互语法,重新定义人工智能与物理世界的对话方式。MCP协议如同为AI系统装上了“万能接口”…...
基于YOLO的半自动化标注方法:提升铁路视频缺陷检测效率
论文地址:https://arxiv.org/pdf/2504.01010 1. 论文结构概述 本文提出了一种半自动化标注方法,旨在解决铁路缺陷检测中大规模图像/视频数据集标注成本高、耗时长的问题。论文结构清晰,分为以下核心部分: 引言(Introduction) 强调传统手动标注的痛点(耗时、易错、…...
Spring Boot 国际化配置项详解
Spring Boot 国际化配置项详解 1. 核心配置项分类 将配置项分为以下类别,便于快速定位: 1.1 消息源配置(MessageSource 相关) 控制属性文件的加载、编码、缓存等行为。 配置项作用默认值示例说明spring.messages.basename指定属…...
【区块链安全 | 第三十八篇】合约审计之获取私有数据(二)
文章目录 前言漏洞代码代码审计攻击步骤修复建议审计思路 前言 在【区块链安全 | 第三十七篇】合约审计之获取私有数据(一)中,介绍了私有数据、访问私有数据实例、Solidity 中的数据存储方式等知识,本文通过分析具体合约代码进行…...
