Spring WebClient调用REST API时遭遇Jackson NoSuchMethodError问题求助
Spring WebClient解析响应时NoSuchMethodError问题解决
环境信息
- Spring Framework 5.3.18(包含spring-webflux)
- reactor-netty 1.1.1
- reactor-core 3.5.1
相关代码
@RestController @RequestMapping("/messages") public class WsmessageController { @Autowired private WSMessageService wSMessageService; @GetMapping @ResponseStatus(HttpStatus.OK) public List<Wsmessage> findAllWSMessages() { List<Wsmessage> wsMessages = wSMessageService.findAllWSMessages("SELECT u FROM Wsmessage u"); System.out.println("SERVER GET ALL MESSAGES = " + wsMessages); return wsMessages; } } public Flux<Message> findAll() { Flux<Message> messages = webClient.get().uri("/messages").retrieve().bodyToFlux(Message.class); return messages; } List<Message> messagesblock = messages.collectList().block();
问题描述
调用上述REST API时,客户端触发JVM致命异常并阻塞,服务端已成功返回数据,但客户端解析响应失败,报错如下:
java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonFactory.createNonBlockingByteArrayParser()Lcom/fasterxml/jackson/core/JsonParser;
完整堆栈跟踪:
12:10:05,545 WARN [reactor.core.Exceptions] (reactor-http-nio-3) throwIfFatal检测到JVM致命异常,如下抛出并记录:: java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonFactory.createNonBlockingByteArrayParser()Lcom/fasterxml/jackson/core/JsonParser; at org.springframework.http.codec.json.Jackson2Tokenizer.tokenize(Jackson2Tokenizer.java:243) at org.springframework.http.codec.json.AbstractJackson2Decoder.decode(AbstractJackson2Decoder.java:138) at org.springframework.http.codec.DecoderHttpMessageReader.read(DecoderHttpMessageReader.java:104) at org.springframework.web.reactive.function.BodyExtractors.lambda$readToFlux$16(BodyExtractors.java:219) at java.util.Optional.orElseGet(Optional.java:267) at org.springframework.web.reactive.function.BodyExtractors.readToFlux(BodyExtractors.java:219) at org.springframework.web.reactive.function.BodyExtractors.lambda$null$3(BodyExtractors.java:115) at java.util.Optional.map(Optional.java:215) at org.springframework.web.reactive.function.BodyExtractors.readWithMessageReaders(BodyExtractors.java:196) at org.springframework.web.reactive.function.BodyExtractors.lambda$toFlux$5(BodyExtractors.java:114) at org.springframework.web.reactive.function.client.DefaultClientResponse.body(DefaultClientResponse.java:131) at org.springframework.web.reactive.function.client.DefaultClientResponse.bodyToFlux(DefaultClientResponse.java:158) at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultResponseSpec.lambda$bodyToFlux$4(DefaultWebClient.java:555) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:163) at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:74) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539) at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122) at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:250) at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2545) at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.request(FluxContextWrite.java:136) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onSubscribeInner(MonoFlatMapMany.java:150) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onSubscribe(MonoFlatMapMany.java:245) at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onSubscribe(FluxContextWrite.java:101) at reactor.core.publisher.FluxJust.subscribe(FluxJust.java:68) at reactor.core.publisher.Flux.subscribe(Flux.java:8660) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:195) at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99) at reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.onNext(FluxRetryWhen.java:174) at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:172) at reactor.netty.http.client.HttpClientConnect$HttpIOHandlerObserver.onStateChange(HttpClientConnect.java:431) at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:705) at reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.onStateChange(DefaultPooledConnectionProvider.java:195) at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnection.onStateChange(DefaultPooledConnectionProvider.java:456) at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:637) at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:113) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:333) at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:454) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Thread.java:748)
问题原因
createNonBlockingByteArrayParser()是Jackson Core 2.12版本新增的方法,而Spring WebFlux 5.3.x依赖的Jackson版本要求至少为2.12.x。你的项目中大概率引入了更低版本的Jackson Core,导致运行时找不到该方法,触发NoSuchMethodError。
解决方法
1. 统一Jackson版本
在依赖管理文件中指定与Spring 5.3.18兼容的Jackson版本(推荐2.12.x或2.13.x),确保所有Jackson相关依赖版本一致:
Maven(pom.xml)
<properties> <jackson.version>2.12.7</jackson.version> </properties> <dependencies> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>${jackson.version}</version> </dependency> </dependencies>
Gradle(build.gradle)
ext { jacksonVersion = '2.12.7' } dependencies { implementation "com.fasterxml.jackson.core:jackson-core:$jacksonVersion" implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" implementation "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" }
2. 排查并解决依赖冲突
执行依赖分析命令,找出引入低版本Jackson的依赖,并排除:
- Maven:
mvn dependency:tree,查找所有Jackson相关依赖的路径,排除低版本。 - Gradle:
gradle dependencies,同理排查并排除冲突依赖。
3. 验证修复
重新构建项目后,再次调用WebClient接口,确认异常消失,响应能正常解析。
内容的提问来源于stack exchange,提问作者Bouchaib Souhail
相关产品推荐
相关产品推荐

