Spring Boot 2.7.12迁移至3.x时遭遇HttpMessageConversionException及WireMock返回异常状态码问题求助
嗨,看起来你在Spring Boot版本迁移的路上踩了好几个连环坑,我来帮你一步步拆解和解决这些问题:
首先解决最初的NoClassDefFoundError: jakarta/servlet/http/HttpSessionContext问题
你手动引入jakarta.servlet-api 5.0.0的思路其实跑偏了——Spring Boot 3.x的spring-boot-starter-jetty已经内置适配了Jakarta EE 9+的Servlet API版本,完全不需要手动添加这个依赖。手动引入反而会破坏Spring Boot的依赖版本管理,导致后续出现序列化冲突,这也是你第二个问题的诱因之一。
解决方案:直接移除POM中手动添加的jakarta.servlet-api依赖,让spring-boot-starter-jetty自动管理Servlet API的版本。
然后处理HttpMethod序列化失败的问题
你自定义序列化器的方向是对的,但你完全重写ObjectMapper的方式会覆盖Spring Boot自动配置的Jackson全局设置(比如Spring模块集成、日期格式化、默认序列化规则等),这很可能是后续WireMock返回500的根源。
给你两个更稳妥的方案:
临时规避方案(快速验证)
在application-test.properties中添加配置,让Jackson忽略空Bean的序列化失败:spring.jackson.serialization.fail-on-empty-beans=false这个方案能快速消除序列化异常,但只是治标不治本。
正确自定义Jackson配置的方式
不要完全重建ObjectMapper,而是通过Jackson2ObjectMapperBuilderCustomizer来扩展Spring的默认配置,这样不会破坏原有功能:@Configuration public class JacksonConfiguration { @Bean public Jackson2ObjectMapperBuilderCustomizer httpMethodJacksonCustomizer() { return builder -> { builder.serializerByType(HttpMethod.class, new HttpMethodSerializer()); builder.deserializerByType(HttpMethod.class, new HttpMethodDeserializer()); }; } }这样既添加了
HttpMethod的自定义序列化规则,又保留了Spring Boot默认的Jackson配置。
最后搞定WireMock返回500的问题
这个问题的核心是迁移前后请求的序列化格式发生了变化,导致WireMock的Stub无法匹配请求,从而返回默认的500错误。你可以按以下步骤排查:
- 先恢复Spring Boot默认的Jackson配置(去掉之前的全自定义
ObjectMapper),用上面的Jackson2ObjectMapperBuilderCustomizer方案,或者临时用FAIL_ON_EMPTY_BEANS配置,先确保序列化异常消失。 - 在测试中打印发送给WireMock的请求体,对比Spring Boot 2.7.12和3.x版本的请求格式差异:比如
method字段的大小写、是否有额外字段、字段名是否变化等。 - 根据差异调整WireMock的Stub配置,确保能正确匹配新的请求格式。比如如果之前Stub期望
method是小写get,而现在序列化后是大写GET,就需要修改Stub的匹配规则。 - 检查WireMock版本是否兼容Spring Boot 3.x:如果你的WireMock版本太旧,可能和Jakarta EE的类库存在冲突,建议升级到最新稳定版(比如3.x系列)。
总结一下执行步骤
- 移除POM中手动添加的
jakarta.servlet-api依赖 - 用
Jackson2ObjectMapperBuilderCustomizer替代全自定义的ObjectMapper来处理HttpMethod序列化 - 对比迁移前后的请求格式,调整WireMock Stub的匹配规则
- 升级WireMock到兼容Spring Boot 3.x的版本
按照这个流程走,应该能逐步解决你遇到的所有问题。
备注:内容来源于stack exchange,提问作者du-it

