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

news/2024/10/19 15:17:12/

文章目录

    • 类继承体系
    • 核心类与接口说明
    • 底层调用链
    • 完整示例
      • 步骤 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方法来完成。例如:

    java">@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>

java">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接口:

java">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将使用你的自定义转换器来处理序列化和反序列化。

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

java">@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.ppmy.cn/news/1540276.html

相关文章

maven工程怎么将除工程源码外的三方依赖一起打包到jar中

前言 现在&#xff0c;大家都在使用springboot来创建工程&#xff0c;基本很少关注打包的问题&#xff0c;springboot的spring boot maven plugin可以很方便的创建一个可执行的jar文件&#xff0c;并且包含项目的所有依赖。最近改一个老项目&#xff0c;纯maven项目&#xff0…

Matlab 二维绘图命令(第一期)

基本绘图 plot 基本二维绘图函数 格式&#xff1a; plot(x,y,’s’) plot(x1,y1,’s1’,x2,y2,’s2’…) s为一字符串&#xff0c;用于设置绘图颜色和类型 绘图颜色与类型 颜色&#xff1a;b(默认&#xff1a;蓝)、g(绿)、r(红)、c(青)、m(洋红)、y(黄)、k(黑) 线型&am…

三、MyBatis实践:提高持久层数据处理效率(1)(包含mybatis下载官网)

一、Mybatis简介 1.1 简介 https://mybatis.org/mybatis-3/zh/index.html MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投Google Code旗下&#xff0c; iBatis3.x正式更名为MyBatis。代码于…

探索 C# 的进阶特性

随着 C# 语言的不断演进&#xff0c;越来越多的特性被引入&#xff0c;提升了代码的可读性和性能。这些进阶特性为开发者提供了更多简洁而强大的工具&#xff0c;用来编写高效、优雅的代码。本文将介绍 C# 中的一些重要进阶特性&#xff0c;包括属性模式匹配、异常过滤器、记录…

网站建设完成后,多久需要升级迭代一次

网站建设完成后&#xff0c;一般每隔几个月就会进行一次迭代升级。以下是关于网站迭代周期和原因的具体分析&#xff1a; 更新频率&#xff1a;网站在建设完成后&#xff0c;一般每隔几个月就会进行一次迭代升级。这种周期性的更新有助于保持网站的现代感和竞争力。更新目的&a…

微信小程序定位判断点位是否在某个范围内(腾讯地图转百度地图)

业务:比较微信小程序定位是否在系统设置的某个位置的某个范围内 问题:微信小程序的定位是拿的腾讯地图的经纬度(假设为点A),系统设置的某个位置是百度地图的经纬度(假设为点B),需要判断点A是否在点B的Range(米)范围内 解决方案:将腾讯点A的经纬度转换为百度地图的经纬度后再进行…

iptables限速规则

环境&#xff1a; iptables服务器&#xff1a;172.16.12.33 client&#xff1a;192.168.1.2 1、在防火墙上配置客户端的下载速度是1M/s &#xff08;1个包是1.3KB&#xff09; #限速客户端每秒的下载速度是1024KB&#xff0c;超出限制的流量就丢弃 [rootiptables-172-16-12-…

Web安全常见问题

OSI七层模型和HTTP请求 OSI 物理层-数据链路层-网络层-传输层-会话层-表示层-应用层 五层协议 物理层-数据链路层-网络层-传输层-应用层 HTTP请求类型&#xff1a; GET 请求的数据在url头 POST 请求的数据在请求体 PUT 更新资源 DELETE 删除 CONNECT http/1.1协议中预留…