You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring中StringHttpMessageConverter未关闭输入流致文件句柄泄漏如何解决

@RequestPart字符串参数文件句柄泄漏修复方案

根因说明

默认StringHttpMessageConverter读取请求输入流后未显式关闭,导致Tomcat生成的upload_*.tmp临时文件句柄长期被占用,引发泄漏。Jackson系列转换器内部会通过Parser主动释放流资源,因此无该问题。

可选修复方案

方案1:重写StringHttpMessageConverter(兼容性最好,无需改业务代码)

自定义消息转换器,用try-with-resources语法自动关闭输入流,再替换默认的转换器:

// 自定义关流的String转换器
public class ClosableStringHttpMessageConverter extends StringHttpMessageConverter {
    @Override
    protected String readInternal(Class<? extends String> clazz, HttpInputMessage inputMessage) throws IOException {
        try (InputStream is = inputMessage.getBody()) {
            return StreamUtils.copyToString(is, getDefaultCharset());
        }
    }
}

注册到Spring MVC配置中:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 放到最前面,覆盖默认的StringHttpMessageConverter
        converters.add(0, new ClosableStringHttpMessageConverter());
    }
}

方案2:升级Spring Framework版本

该泄漏问题属于Spring官方已知BUG,在Spring Framework 5.3.22、6.0.0及以上版本中已经被官方修复,直接升级依赖版本即可原生解决问题,不需要修改业务代码。

方案3:封装字符串为POJO,使用Jackson反序列化

将字符串参数封装为简单对象,Spring会自动使用Jackson的消息转换器处理,Jackson内部会主动关闭流,避免泄漏:

// 定义封装对象
public class MetaData {
    private String value;
    // 省略getter、setter
}

// 接口写法不变,仅调整参数类型
@PostMapping("/upload")
public String upload(@RequestPart("meta-data") MetaData metaData, 
                     @RequestPart("file") MultipartFile file) {
    String meta = metaData.getValue();
    // 后续业务逻辑
}

补充说明

你目前使用的@RequestParam替代方案本身符合Spring规范,如果业务场景不需要处理multipart请求中的复杂内容类型,可以继续使用,不存在功能缺陷。

内容的提问来源于stack exchange,提问作者Sam S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 18:45:01