【Spring相关技术】spring进阶-自定义请求报文转对象HttpMessageConverter

文章目录

    • 类继承体系
    • 核心类与接口说明
    • 底层调用链
    • 完整示例
      • 步骤 1: 创建自定义的HttpMessageConverter
      • 步骤 2: 配置Spring MVC使用自定义转换器
      • 步骤 3: 使用自定义转换器
    • 相关文献

类继承体系

默认转换器即springmvc默认的转换器, 用的比较多的是以下两种, 无需自己声明以及使用。
相关的类的内容这里不做展示,有兴趣大家可以下载源码看一下。

  • 默认json转换器
    json-convertor

  • 默认xml转换器
    xml-convertor

核心类与接口说明

在Spring框架中,HttpMessageConverter 是一个非常重要的接口,它用于在HTTP请求和响应与Java对象之间进行转换。如果你需要实现自定义的报文转换器,可以按照以下步骤进行:

  1. 实现HttpMessageConverter接口:创建一个类实现HttpMessageConverter<T>接口,其中T是你希望转换的目标类型。你需要实现以下方法:

    • canRead(Class<?> clazz, MediaType mediaType):判断转换器是否能够读取指定类型和媒体类型的数据。
    • canWrite(Class<?> clazz, MediaType mediaType):判断转换器是否能够写入指定类型和媒体类型的数据。
    • getSupportedMediaTypes():返回转换器支持的媒体类型列表。
    • read(Class<? extends T> clazz, HttpInputMessage inputMessage):从HttpInputMessage中读取数据并转换为T类型的对象。
    • write(T t, MediaType contentType, HttpOutputMessage outputMessage):将T类型的对象转换并写入HttpOutputMessage中。
  2. 继承AbstractHttpMessageConverter:Spring提供了AbstractHttpMessageConverter类,它简化了HttpMessageConverter接口的实现。你只需要重写supports(Class<?> clazz)readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)writeInternal(T t, HttpOutputMessage outputMessage)方法。

  3. 配置Spring MVC使用自定义转换器:你需要在Spring的配置中注册自定义的HttpMessageConverter。这可以通过实现WebMvcConfigurer接口并重写configureMessageConvertersextendMessageConverters方法来完成。例如:

    @Configuration
    public class WebConfig implements WebMvcConfigurer {@Overridepublic void extendMessageConverters(List<HttpMessageConverter<?>> converters) {converters.add(new MyMessageConverter());}
    }
    

    其中MyMessageConverter是你的自定义转换器类。

  4. 使用自定义转换器:一旦注册,Spring MVC将自动使用你的自定义转换器来处理匹配的请求和响应。

在实现自定义转换器时,你可以定义自己的序列化和反序列化逻辑,例如处理XML、JSON或其他自定义格式的数据。自定义转换器可以让你更灵活地处理HTTP请求和响应数据,满足特定的业务需求。

底层调用链

在Spring MVC中,HttpMessageConverter 是一个核心接口,它负责将HTTP请求和响应的消息体与Java对象之间进行转换。下面我将解释Spring MVC中调用这些报文转换器的流程。

  1. 请求到达:当一个HTTP请求到达Spring MVC的DispatcherServlet时,它将请求委托给RequestMappingHandlerMapping来解析。

  2. 选择处理器RequestMappingHandlerMapping根据请求的URL和HTTP方法等信息找到匹配的控制器方法。

  3. 处理器适配器:找到控制器方法后,DispatcherServlet使用一个适当的HandlerAdapter来处理请求。对于使用@RequestMapping注解的方法,通常会使用RequestMappingHandlerAdapter

  4. 调用链

    • RequestMappingHandlerAdapter中的invokeHandlerMethod方法被调用。
    • 在这个方法内部,会创建一个ServletInvocableHandlerMethod对象,该对象封装了对控制器方法的调用。
    • ServletInvocableHandlerMethod对象持有从RequestMappingHandlerAdapter获取的messageConverters列表,这个列表包含了所有可用的消息转换器。
  5. 参数解析

    • 如果控制器方法有参数,并且这些参数需要从请求体中读取(例如,使用了@RequestBody注解),ServletInvocableHandlerMethod将使用RequestResponseBodyMethodProcessor来解析这些参数。
    • RequestResponseBodyMethodProcessor会遍历所有的messageConverters,使用canRead方法检查哪个转换器能够读取给定的媒体类型(Media Type)和目标类。
    • 一旦找到合适的转换器,它将使用read方法将请求体转换为相应的Java对象。
  6. 控制器方法执行:参数解析完成后,控制器方法被执行。

  7. 处理返回值

    • 控制器方法执行后,如果方法上有@ResponseBody注解,ServletInvocableHandlerMethod将再次使用RequestResponseBodyMethodProcessor来处理返回值。
    • RequestResponseBodyMethodProcessor会遍历所有的messageConverters,使用canWrite方法检查哪个转换器能够写入给定的媒体类型和对象类。
    • 找到合适的转换器后,它将使用write方法将Java对象转换为响应体消息。
  8. 响应返回:最终,转换后的消息体被写入HTTP响应中,并返回给客户端。

在整个调用链中,HttpMessageConverter的实现类负责具体的序列化和反序列化逻辑。开发者可以通过实现WebMvcConfigurer接口的extendMessageConverters方法来添加自定义的转换器,或者通过配置文件中的<mvc:message-converters>标签来注册自定义转换器。

这个调用流程涉及到了多个组件和步骤,每个组件都在Spring MVC的请求处理中扮演了特定的角色。通过这种方式,Spring MVC提供了高度可定制的消息转换机制,以适应不同的数据处理需求。

完整示例

下面我将通过一个简单的例子来说明如何创建并集成一个自定义的HttpMessageConverter到Spring MVC中。

假设我们有一个简单的Java对象MyObject,我们想要通过一种非标准的媒体类型application/x-myobject来序列化和反序列化这个对象。我们将创建一个自定义的HttpMessageConverter来处理这个任务。

步骤 1: 创建自定义的HttpMessageConverter

首先,我们创建一个类MyObjectHttpMessageConverter,继承自AbstractHttpMessageConverter<MyObject>

import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.util.StreamUtils;import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;public class MyObjectHttpMessageConverter extends AbstractHttpMessageConverter<MyObject> {public MyObjectHttpMessageConverter() {super(new MediaType("application", "x-myobject"));}@Overrideprotected boolean supports(Class<?> clazz) {return MyObject.class.isAssignableFrom(clazz);}@Overrideprotected MyObject readInternal(Class<? extends MyObject> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {String body = StreamUtils.copyToString(inputMessage.getBody(), Charset.defaultCharset());// 假设MyObject的构造函数接受一个字符串return new MyObject(body);}@Overrideprotected void writeInternal(MyObject myObject, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {OutputStreamWriter writer = new OutputStreamWriter(outputMessage.getBody(), getCharset());// 假设我们要将MyObject转换成字符串进行输出writer.write(myObject.toString());writer.flush();}
}

步骤 2: 配置Spring MVC使用自定义转换器

接下来,我们需要在Spring MVC的配置中注册我们的自定义转换器。如果你使用的是Java配置,可以像下面这样实现WebMvcConfigurer接口:

import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.List;@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void extendMessageConverters(List<HttpMessageConverter<?>> converters) {// 如何自定义的转换器与默认转换器冲突,可以将自己的转换器放到默认转换器前面converters.add(new MyObjectHttpMessageConverter());}
}

如果你使用的是XML配置,可以在<mvc:annotation-driven/>标签中添加一个<bean>来注册你的转换器:

<mvc:annotation-driven><mvc:message-converters><bean class="com.example.MyObjectHttpMessageConverter"/></mvc:message-converters>
</mvc:annotation-driven>

步骤 3: 使用自定义转换器

现在,当你的控制器方法返回一个MyObject类型的实例,或者接受一个MyObject类型的参数时,Spring MVC将使用你的自定义转换器来处理序列化和反序列化。

例如,你的控制器可能看起来像这样:

@RestController
public class MyObjectController {@PostMapping(value = "/myobject", consumes = "application/x-myobject")public MyObject handleMyObject(@RequestBody MyObject myObject) {// 处理myObjectreturn myObject;}
}

在这个例子中,当客户端以application/x-myobject类型发送数据到/myobject端点时,Spring MVC将使用MyObjectHttpMessageConverter来解析请求体中的字符串并创建MyObject实例。同样,当控制器方法返回一个MyObject实例时,Spring MVC也将使用这个转换器将实例转换为响应体。

这样,你就成功地将自定义的报文转换器集成到了Spring MVC中。

相关文献

【java知识】java基础-xstream解析xml

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

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

相关文章

18063 圈中的游戏

### 思路 这个问题是经典的约瑟夫环问题。我们可以使用链表来模拟这个过程。具体步骤如下&#xff1a; 1. 创建一个循环链表&#xff0c;表示所有人。 2. 从第一个人开始&#xff0c;依次报数。 3. 每报到3的人退出圈子&#xff0c;直到只剩下一个人。 ### 伪代码 function j…

TuyaOS开发学习笔记(4)——BLE开发搭建环境、编译烧写(NRF52832)

一、搭建环境 1.1 官方资料 TuyaOS 1.2 安装Visual Studio Code 官网下载&#xff1a;https://code.visualstudio.com 百度网盘&#xff1a;https://pan.baidu.com/s/1R62HT0PVmVzMwOXtCmIQwA 提取码&#xff1a;g9fb 1.3 安装Tuya Wind IDE 启动 Visual Studio Code 后&am…

肽合同制造(CDMO):北美和欧洲是全球最大肽合同制造(CDMO)消费地区

据 HengCe 最新调研&#xff0c;2023年中国肽合同制造&#xff08;CDMO&#xff09;市场销售收入达到了 万元&#xff0c;预计2030年可以达到 万元&#xff0c;2024-2030期间年复合增长率(CAGR)为 %。本研究项目旨在梳理肽合同制造&#xff08;CDMO&#xff09;领域产品系列&am…

前端布局与响应式设计综合指南(末)

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Css篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来Css篇专栏内容:前端布局与响应式设计综合指南(末) 目录 61、为什么要初始化CSS样式 62、CSS3 有哪些新特性 63、…

microsoft edge浏览器卡死问题

win11经常遇到microsoft edge浏览器卡死的情况&#xff0c;有时候是一会没用浏览器就全部卡死&#xff0c;有时候是锁屏或者电脑休眠浏览器就不能用&#xff0c;找了很多的办法都没好使&#xff0c;用以下方法好使了&#xff1a; edge浏览器中打开 edge://settings/system 把 …

【从零开始的LeetCode-算法】2135. 统计追加字母可以获得的单词数

给你两个下标从 0 开始的字符串数组 startWords 和 targetWords 。每个字符串都仅由 小写英文字母 组成。 对于 targetWords 中的每个字符串&#xff0c;检查是否能够从 startWords 中选出一个字符串&#xff0c;执行一次 转换操作 &#xff0c;得到的结果与当前 targetWords …

nemo-guardrails简单应用

环境&#xff1a;openEuler、python 3.11.6、nemoguardrails 0.10.1、Azure openAi 背景&#xff1a;工作需要&#xff0c;进行调研期间&#xff0c;发现问题太多&#xff0c;且国内网站好多没说明具体问题 时间&#xff1a;20241014 说明&#xff1a;搭建过程中主要是下载h…

apache.poi读取.xls文件时The content of an excel record cannot exceed 8224 bytes

目录 问题描述版本定位&#xff1a;打印size最大的Record定位&#xff1a;RefSubRecord解决代码 问题描述 使用apache.poi读取.xls文件时有The content of an excel record cannot exceed 8224 bytes的报错。待读取的文件的内容也是通过apache.poi写入的&#xff0c;我的文件修…

深入剖析递归算法:原理、特点、应用与优化策略

在上一篇文章&#x1f449;【剖析十大经典二叉树题目】中&#xff0c;运用到了大量的递归算法&#xff0c;故本文将解析递归算法。 目录 &#x1f4af;引言 &#x1f4af;递归算法的定义与原理 ⭐定义 ⭐原理 &#x1f4af;递归算法的特点 ⭐简洁性 ⭐可读性 ⭐通用性 …

【拼多多】拼多多批发 | 拼多多手机端 | anti_content |

所有的anti_content都可以用官网的anti_content的生成

MySQL 的数据类型

1.整数类型 1.1 tinyint tinyint 为小整数类型&#xff0c;存储空间为1个字节&#xff08;8位&#xff09;&#xff0c;有符号范围-128 ~ 127&#xff0c;无符号范围 0 ~ 255,此类型通常在数据库中表示类型的字段&#xff0c;如某一字段 type 表示学科,其中 “type1” 表示语文…

Light灯光组件+组件的相关操作+游戏资源的加载

Light灯光组件 Type: Directional:平行光&#xff0c;模仿的是太阳光 Spot:聚光灯 Area:区域光 Color&#xff1a; 颜色值 Mode: RealTime:实时 Mix:混合 Baked:烘焙 Intersity: 光照强度 Indirect Multiplier:光照强度乘数 Shadow Type:影子设置&#xff1a;…

【python学习】1-2 配置python系统环境变量

1.点击“我的电脑”右键&#xff0c;点击属性&#xff0c;点击“高级系统设置”&#xff0c;再点击环境变量。 2.选择“系统变量”中的Path后&#xff0c;点击编辑。 3.点击新建&#xff0c;添加如图两个路径&#xff0c;即是python安装的路径位置后&#xff0c;点击确定。

C# 实现调用函数,打印日志(通过反射代理、非IOC)

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C# &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff…

大数据ETL数据提取转换和加载处理

什么是 ETL&#xff1f; 提取转换加载&#xff08;英语&#xff1a;Extract, transform, load&#xff0c;简称ETL&#xff09;&#xff0c;用来描述将资料从来源端经过抽取、转置、加载至目的端的过程。ETL一词较常用在数据仓库&#xff0c;但其对象并不限于数据仓库。 ETL&…

某知名国企面试题

引言 金九银十&#xff0c;求职热潮再度来袭。最近&#xff0c;有位同学去一家知名国企应聘&#xff0c;回来后带回了一套面试题。这套面试题非常典型&#xff0c;其中包含了许多供应链金融方面的典型问题。这些问题很有分享的价值&#xff0c;大家也可以先自己独立思考一下&a…

PFC和LLC的本质和为什么要用PFC和LLC电路原因

我们可以用电感和电容的特性,以及电压和电流之间的不同步原理来解释PFC(功率因数校正)和LLC(谐振变换器)。 电感和电容的基本概念 电感(Inductor): 电感是一种储存电能的组件。它的电流变化比较慢,电流在电感中延迟,而电压变化得比较快。可以把电感想象成一个“滞后…

接口自动化测试介入项目管理流程

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 下图为接口自动化测试介入梧桐项目管理流程图 前景和目标&#xff1a; 现在公司的项目流程都是全部开发完成后提交到测试环境进行测试&#xff0c;导致测试人员在…

基于FPGA的以太网设计(三)

通过前文介绍了RGMII接口时序我们可以知道&#xff0c;RGMII接口是在时钟信号的上升沿和下降沿均进行数据的传输&#xff0c;而FPGA则在时钟的单沿传输数据&#xff0c;因此我们需要编写代码将RGMII接口转换为GMII接口。 由于前面的介绍我们知道RTL8211默认工作在延时状态&…

深入计算机语言之C++:类与对象(上)

&#x1f511;&#x1f511;博客主页&#xff1a;阿客不是客 &#x1f353;&#x1f353;系列专栏&#xff1a;从C语言到C语言的渐深学习 欢迎来到泊舟小课堂 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 前面我们学习了关于c语言的一些基础知识&#xff…