由@EnableWebMvc注解引发的Jackson解析异常

2023-12-14 17:12

本文主要是介绍由@EnableWebMvc注解引发的Jackson解析异常,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

同事合了代码到开发分支,并没有涉及到改动的类却报错。错误信息如下:

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; 
nested exception is org.springframework.http.converter.HttpMessageConversionException: 
Type definition error: [simple type, class com.tongweb.demo.bean.Registration];
nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Cannot construct instance of `com.tongweb.demo.bean.Registration` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

这个错误的大概意思就是jackson解析Registration类时出现了错误,说Registration类缺少默认构造函数。这个类是Controller中一个方法的入参。示例代码如下:

@PostMapping(path = "/instances", consumes = MediaType.APPLICATION_JSON_VALUE)  
public String register(@RequestBody Registration registration) {  Registration withSource = Registration.copyOf(registration).source("http-api").build(); return withSource.toString();  
}

相关代码并不涉及到改动,自从我同事代码合过来就开始报错,很不应该。起初我猜测是某些jar冲突引起的。但是查看了他合并过来的代码,也并未涉及到jar依赖的升级变更等。对于这个错误网上是有很多解决方案的,比如加个构造函数。但是不排查到导致问题的原因,这总归是个雷。于是我开启了漫长的排除过程。

首先考虑是jar冲突导致。我重新写了一个新项目,沿用了我目前的所有jar。访问instances接口,jackson解析并不会报错。那只有跟踪源码了。

spring提供了一个Jackson的HTTP消息转换器的配置JacksonHttpMessageConvertersConfiguration,会创建一个MappingJackson2HttpMessageConverterMappingJackson2HttpMessageConverter会负责解析Registration类。特别说明Registration类只有有参构造函数,没有无参构造函数。

HttpMessageConverters负责管理Spring Boot应用程序中使用的HttpMessageConverters。提供了一种向web应用程序添加和合并其他HttpMessageConverter的方便方法。
如果需要,可以向特定的附加转换器注册此bean的实例,否则将使用默认转换器。说白了就是Spring Boot应用程序中的各个转换就是在HttpMessageConverters中。

按理来说MappingJackson2HttpMessageConverter也是HttpMessageConverters中的一员。但是我跟踪源码发现MappingJackson2HttpMessageConverter并未出现在HttpMessageConverters中。跟踪源码WebMvcConfigurationSupport类,源码如下:


protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {  messageConverters.add(new ByteArrayHttpMessageConverter());  messageConverters.add(new StringHttpMessageConverter());  messageConverters.add(new ResourceHttpMessageConverter());  messageConverters.add(new ResourceRegionHttpMessageConverter());...
}

这一段关键代码是把HttpMessageConverters添加到messageConverters。后续解析@RequestBody修饰的类就会从中选择对应的Converter。当源码进行到这一步的时候。我发现MappingJackson2HttpMessageConverter并不存在。它的加载顺序发生在了addDefaultHttpMessageConverters方法执行之后。这就导致messageConverters中并没有MappingJackson2HttpMessageConverter。所以当@RequestBody修饰的类没有无参构造函数的时候解析就报错了。一个正常的应用程序MappingJackson2HttpMessageConverter会优先被加载。找到问题的原因就方便多了。

为什么JacksonHttpMessageConvertersConfiguration的加载顺序会晚于WebMvcConfigurationSupport类呢?换而言之有哪些因素会影响WebMvcConfigurationSupport类的加载。答案就是@EnableWebMvc注解!!

如果在代码中使用了@EnableWebMvc注解,那么WebMvcConfigurationSupport就会比JacksonHttpMessageConvertersConfiguration优先加载,因为@EnableWebMvc注解会导入DelegatingWebMvcConfiguration类,而这个类继承了WebMvcConfigurationSupport类,并且有@Order注解,指定了加载顺序。

这样的话,Spring Boot的默认MVC配置就会被关闭,你需要自己配置Spring MVC的功能,例如拦截器、视图解析器、消息转换器等。

最后附录一下导致问题发生的代码:

在这里插入图片描述

这篇关于由@EnableWebMvc注解引发的Jackson解析异常的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/493359

相关文章

python常见环境管理工具超全解析

《python常见环境管理工具超全解析》在Python开发中,管理多个项目及其依赖项通常是一个挑战,下面:本文主要介绍python常见环境管理工具的相关资料,文中通过代码介绍的非常详细,需要的朋友... 目录1. conda2. pip3. uvuv 工具自动创建和管理环境的特点4. setup.py5.

全面解析HTML5中Checkbox标签

《全面解析HTML5中Checkbox标签》Checkbox是HTML5中非常重要的表单元素之一,通过合理使用其属性和样式自定义方法,可以为用户提供丰富多样的交互体验,这篇文章给大家介绍HTML5中C... 在html5中,Checkbox(复选框)是一种常用的表单元素,允许用户在一组选项中选择多个项目。本

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

mapstruct中的@Mapper注解的基本用法

《mapstruct中的@Mapper注解的基本用法》在MapStruct中,@Mapper注解是核心注解之一,用于标记一个接口或抽象类为MapStruct的映射器(Mapper),本文给大家介绍ma... 目录1. 基本用法2. 常用属性3. 高级用法4. 注意事项5. 总结6. 编译异常处理在MapSt

Python包管理工具核心指令uvx举例详细解析

《Python包管理工具核心指令uvx举例详细解析》:本文主要介绍Python包管理工具核心指令uvx的相关资料,uvx是uv工具链中用于临时运行Python命令行工具的高效执行器,依托Rust实... 目录一、uvx 的定位与核心功能二、uvx 的典型应用场景三、uvx 与传统工具对比四、uvx 的技术实

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

Redis过期删除机制与内存淘汰策略的解析指南

《Redis过期删除机制与内存淘汰策略的解析指南》在使用Redis构建缓存系统时,很多开发者只设置了EXPIRE但却忽略了背后Redis的过期删除机制与内存淘汰策略,下面小编就来和大家详细介绍一下... 目录1、简述2、Redis http://www.chinasem.cn的过期删除策略(Key Expir

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Spring组件实例化扩展点之InstantiationAwareBeanPostProcessor使用场景解析

《Spring组件实例化扩展点之InstantiationAwareBeanPostProcessor使用场景解析》InstantiationAwareBeanPostProcessor是Spring... 目录一、什么是InstantiationAwareBeanPostProcessor?二、核心方法解