Spring Boot出现java.io.EOFException异常的原因及解决咨询
问题分析与解决:Spring Boot 2.4.0中POST请求触发EOFException
环境与代码信息
- Spring Boot版本:2.4.0
- JDK版本:1.8
Controller代码:
@RestController public class HelloController { @RequestMapping("/hello") public Object hello(@RequestParam(value = "name") String name) { name+="ok!"; return "ok"; } }
curl请求命令:
curl -X POST "http://localhost:8080/hello?name=world"
异常日志
2023-12-28 21:39:20.690 DEBUG 95860 --- [nio-8080-exec-2] o.a.coyote.http11.Http11InputBuffer : Before fill(): [true], parsingRequestLine: [true], parsingRequestLinePhase: [0], parsingRequestLineStart: [0], byteBuffer.position() [0] 2023-12-28 21:39:20.690 DEBUG 95860 --- [nio-8080-exec-2] o.a.tomcat.util.net.SocketWrapperBase : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@4adb5b2d:org.apache.tomcat.util.net.NioChannel@7d089058:java.nio.channels.SocketChannel[connected local=/127.0.0.1:8080 remote=/127.0.0.1:62826]], Read from buffer: [0] 2023-12-28 21:39:22.985 DEBUG 95860 --- [nio-8080-exec-2] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header java.io.EOFException: null at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1231) ~[tomcat-embed-core-9.0.39.jar:9.0.39] at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpoint.java:1141) ~[tomcat-embed-core-9.0.39.jar:9.0.39] at org.apache.coyote.http11.Http11InputBuffer.fill(Http11InputBuffer.java:795) ~[tomcat-embed-core-9.0.39.jar:9.0.39] at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:359) ~[tomcat-embed-core-9.0.39.jar:9.0.39] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:261) ~[tomcat-embed-core-9.0.39.jar:9.0.39] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.39.jar:9.0.39] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.39.jar:9.0.39] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) ~[tomcat-embed-core-9.0.39.jar:9.0.39] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.39.jar:9.0.39] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.39.jar:9.0.39] at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
已尝试的无效操作
- 修改curl请求,添加Content-Length请求头
- 携带Transfer-Encoding=chunked请求头发送请求
- 在application.properties中设置
server.ssl.enable=false
异常原因分析
这个EOFException本质是Tomcat在解析HTTP请求时,提前读到了流的末尾,未接收到完整请求数据。结合场景,核心原因有两点:
- POST请求无请求体但Tomcat期望接收:使用
-X POST时,curl默认不发送请求体,但Tomcat对POST请求会等待读取请求体数据。当curl发送完请求头直接关闭连接,Tomcat尝试读取请求体时就会触发EOFException。 - Tomcat版本兼容性问题:Spring Boot 2.4.0适配的Tomcat 9.0.39,其NIO端点处理无请求体的POST请求时,会进入等待读取数据的状态,超时后抛出EOF异常,属于该版本的特定问题。
有效解决思路
思路1:调整curl请求方式
如果接口仅需URL参数,直接改用GET请求:
curl "http://localhost:8080/hello?name=world"
若必须用POST,需明确告知curl发送空请求体,添加-d ''参数:
curl -X POST -d '' "http://localhost:8080/hello?name=world"
思路2:限制Controller的请求方法
如果接口不需要支持POST,直接指定@RequestMapping的method为GET:
@RestController public class HelloController { @RequestMapping(value = "/hello", method = RequestMethod.GET) public Object hello(@RequestParam(value = "name") String name) { name+="ok!"; return "ok"; } }
这样POST请求会直接返回405 Method Not Allowed,避免触发Tomcat异常。
思路3:升级Spring Boot版本
Spring Boot 2.4.x后续版本(如2.4.13及以上)适配的Tomcat已修复该NIO处理问题,升级版本可从根本解决异常。修改pom.xml中的依赖版本:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.13</version> <relativePath/> </parent>
内容的提问来源于stack exchange,提问作者wenliangzeng-coder
相关产品推荐
相关产品推荐

