当前位置: 首页 > ops >正文

spring mvc HttpMessageConverter 消息转换器

HttpMessageConverter 主要在 Spring MVC 中用于处理 HTTP 請求和响应。它的核心作用是将 HTTP请求体转换成 Java对象,以及將 Java对象转换成 HTTP响应体。这两个场景都是在 @RequestBody / @ResponseBody /注解修饰的请求方法,或HttpEntity类型接口参数上 触发的。

读取请求体(Request → Java 对象)

  • 触发条件:

    • Controller 方法参数上有 @RequestBody
    • 或参数类型是 HttpEntity<T> / RequestEntity<T>
  • 处理流程:

    1. 进入 RequestResponseBodyMethodProcessor#resolveArgument
    2. 调用 readWithMessageConverters(...)(父类 AbstractMessageConverterMethodArgumentResolver
    3. 遍历所有 HttpMessageConverter,找第一个 canRead() 返回 true
    4. 调用该 Converter 的 read() 方法反序列化请求体到 Java 对象

写入响应体(Java 对象 → Response)

  • 触发条件:

    • Controller 方法有 @ResponseBody
    • 或类上有 @RestController
    • 或返回类型是 HttpEntity<T> / ResponseEntity<T>
  • 处理流程:

    1. 进入 RequestResponseBodyMethodProcessor#handleReturnValue
    2. 调用 writeWithMessageConverters(...)(父类 AbstractMessageConverterMethodProcessor
    3. 遍历所有 HttpMessageConverter,找第一个 canWrite() 返回 true
    4. 调用该 Converter 的 write() 方法序列化对象到响应体

HttpMessageConverter的初始化

在WebMvcAutoConfiguration自动装配类中初始化EnableWebMvcConfiguration类,该类是WebMvcConfigurationSupport的子类。getMessageConverters()方法获取所有的消息转换器。

	protected final List<HttpMessageConverter<?>> getMessageConverters() {if (this.messageConverters == null) {//最开始是空的this.messageConverters = new ArrayList<>();//加载自定义的消息转换器configureMessageConverters(this.messageConverters);if (this.messageConverters.isEmpty()) {//如果未配置//加载默认的MessageConverteraddDefaultHttpMessageConverters(this.messageConverters);}//添加扩展MessageConverters ,也是通过ConfigurerextendMessageConverters(this.messageConverters);}return this.messageConverters;}

configureMessageConverters会调用所有的WebMvcConfigurer加载定义的converter

	protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {//这里的configurers是WebMvcConfigurerComposite实例this.configurers.configureMessageConverters(converters);}

WebMvcConfigurerComposite#configureMessageConverters

	public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {for (WebMvcConfigurer delegate : this.delegates) {delegate.configureMessageConverters(converters);}}

在WebMvcAutoConfiguration类中WebMvcAutoConfigurationAdapter就是一个默认的Configurer。其使用HttpMessageConverters来进行converter的初始化。

HttpMessageConverters的初始化在HttpMessageConvertersAutoConfiguration类中进行,首先会从beanFacotry中获取所有已经定义的HttpMessageConverter类型的bean,然后在获取所有的默认

HttpMessageConverters构造函数

	public HttpMessageConverters(boolean addDefaultConverters, Collection<HttpMessageConverter<?>> converters) {List<HttpMessageConverter<?>> combined = getCombinedConverters(converters,addDefaultConverters ? getDefaultConverters() : Collections.emptyList());combined = postProcessConverters(combined);this.converters = Collections.unmodifiableList(combined);}

第一步在HttpMessageConvertersAutoConfiguration类中默认定义了一个StringHttpMessageConverter,还会条件装配@ConditionalOnBean(ObjectMapper.class)一个MappingJackson2HttpMessageConverter类型的json转换其。这样在容器中默认有两个消息转换器。

第二部加载默认的消息转换器,这里入参addDefaultConverters是true,通过getDefaultConverters()方法加载。

	private List<HttpMessageConverter<?>> getDefaultConverters() {List<HttpMessageConverter<?>> converters = new ArrayList<>();if (ClassUtils.isPresent("org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport",null)) {converters.addAll(new WebMvcConfigurationSupport() {public List<HttpMessageConverter<?>> defaultMessageConverters() {return super.getMessageConverters();}}.defaultMessageConverters());}else {converters.addAll(new RestTemplate().getMessageConverters());}reorderXmlConvertersToEnd(converters);return converters;}

这里会走if通过WebMvcConfigurationSupport.defaultMessageConverters()方法加载默认的消息解析器。

	protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {messageConverters.add(new ByteArrayHttpMessageConverter());messageConverters.add(new StringHttpMessageConverter());messageConverters.add(new ResourceHttpMessageConverter());messageConverters.add(new ResourceRegionHttpMessageConverter());if (!shouldIgnoreXml) {try {messageConverters.add(new SourceHttpMessageConverter<>());}catch (Throwable ex) {// Ignore when no TransformerFactory implementation is available...}}messageConverters.add(new AllEncompassingFormHttpMessageConverter());if (romePresent) {messageConverters.add(new AtomFeedHttpMessageConverter());messageConverters.add(new RssChannelHttpMessageConverter());}if (!shouldIgnoreXml) {if (jackson2XmlPresent) {Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();if (this.applicationContext != null) {builder.applicationContext(this.applicationContext);}messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));}else if (jaxb2Present) {messageConverters.add(new Jaxb2RootElementHttpMessageConverter());}}if (kotlinSerializationJsonPresent) {messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());}if (jackson2Present) {Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();if (this.applicationContext != null) {builder.applicationContext(this.applicationContext);}messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));}else if (gsonPresent) {messageConverters.add(new GsonHttpMessageConverter());}else if (jsonbPresent) {messageConverters.add(new JsonbHttpMessageConverter());}if (jackson2SmilePresent) {Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.smile();if (this.applicationContext != null) {builder.applicationContext(this.applicationContext);}messageConverters.add(new MappingJackson2SmileHttpMessageConverter(builder.build()));}if (jackson2CborPresent) {Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.cbor();if (this.applicationContext != null) {builder.applicationContext(this.applicationContext);}messageConverters.add(new MappingJackson2CborHttpMessageConverter(builder.build()));}}

每个消息转换器类处理不同类型的报文体类型,这和报文的MediType相关。通过HttpMessageConverter.canRead( MediaType mediaType)来判断当前converter是否支持当前请求报文。

自定义HttpMessageConverter

如果默认内置的converter不能满足要求,可以进行自定义converter。如请求的body存在转码或加密,或有固定头信息,不是标准的json格式,则可以继承MappingJackson2HttpMessageConverter 类,然后重写对应的read和write方法。

自定义的converter可以通过WebMvcConfigurer加载到容器中。

@Configuration
public class WebConfiguration implements WebMvcConfigurer {@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {converters.add(new MyMappingJackson2HttpMessageConverter());	}
}

也可以通过将自定义的MessageConverter注册未一个bean来让容器自动加载。所有的MessageConverter是存放在一个list中,按converter的注册顺序进行加载。这里就有个小问题,如果converters列表有多个可以处理相同的的请求类型,只会使用第一个匹配到的converter,则可以通过list指定下标形式来设置自定义converter优先级。

http://www.xdnf.cn/news/17724.html

相关文章:

  • 【KALI】第一篇 安装Kali Linux虚拟机之详细操作步骤讲解
  • CNN - 卷积层
  • 利用 Java 爬虫按图搜索 1688 商品(拍立淘)实战指南
  • 高效TypeScript开发:VSCode终极配置指南
  • Varjo XR虚拟现实军用车辆驾驶与操作培训
  • 【MATLAB代码】滑动窗口均值滤波、中值滤波、最小值/最大值滤波对比。订阅专栏后可查看完整代码
  • OpenCV中对图像进行平滑处理的4种方式
  • 《多级缓存架构设计与实现全解析》
  • 【跨越 6G 安全、防御与智能协作:从APT检测到多模态通信再到AI代理语言革命】
  • 机器视觉的磁芯定位贴合应用
  • GraphRAG查询(Query)流程实现原理分析
  • Java+Vue构建的MES信息管理系统,含完整源码,功能涵盖生产跟踪、质量管控等,助力企业实现精细化、智能化生产管理
  • 【16-softmax回归】
  • AI 赋能的软件工程全生命周期应用
  • springboot+vue实现通过poi完成excel
  • Postman 平替 技术解析:架构优势与实战指南
  • 观察者模式(C++)
  • 【Leetcode hot 100】76.最小覆盖字串
  • 【HarmonyOS】Window11家庭中文版开启鸿蒙模拟器失败提示未开启Hyoer-V
  • SwiftUI 页面弹窗操作
  • 用飞算JavaAI一键生成电商平台项目:从需求到落地的高效实践
  • 使用免费API开发口播数字人
  • [机器学习]07-基于多层感知机的鸢尾花数据集分类
  • c++中的Lambda表达式详解
  • Java基础07——基本运算符(本文为个人学习笔记,内容整理自哔哩哔哩UP主【遇见狂神说】的公开课程。 > 所有知识点归属原作者,仅作非商业用途分享)
  • k8s+isulad 网络问题
  • 如何使用 AI 大语言模型解决生活中的实际小事情?
  • 【P81 10-7】OpenCV Python【实战项目】——车辆识别、车流统计(图像/视频加载、图像运算与处理、形态学、轮廓查找、车辆统计及显示)
  • 网络协议序列化工具Protobuf
  • 4.1vue3的setup()