当前位置: 首页 > news >正文

文件上传接口接收不到文件入参

问题描述及现象

POST请求,表单形式传参,Controller层用@RequestParam注解接收;
但是发现接收不到入参;
在这里插入图片描述

排查思路

初步排查

1、参数名称是否一致
2、请求的Content-Type是否是 multipart/form-data
3、是否启用了multipart配置,spring.servlet.multipart.enabled=true
4、文件大小是否超过限制

初步排查后,以上四处均没问题;

进一步排查

问了下deepseek,ds告诉我可能是请求体被项目中的过滤器或拦截器提前消费了,所以传到controller层的时候已经没值了。
然后我检查了一遍项目中的过滤器、拦截器,感觉没有地方会提前消费请求体;并且梳理下了请求进来的顺序; 过滤器–>拦截器 prehandler() -->AOP前置通知–>Controller ;
然后我在过滤器这里打断点,检查参数是否获取到,发现也没有获取到,也就是说,请求一进来的时候,参数就没获取到

深入排查

由于文件传输依赖的是MultipartResolver ,即Multipart解析器,所以我加了如下代码段来验证项目启动时是否正常装配了该解析器

@Autowired(required = false)
private MultipartResolver multipartResolver;@PostConstruct
public void checkResolver() {log.info("MultipartResolver: {}", multipartResolver); // 应输出 StandardServletMultipartResolver
}

经验证,项目启动时,MultipartResolver为null,没有正常装配。
既然没有正常装配,那我手动装配它。于是我加了以下代码:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;@Configuration
public class MultipartConfig {@Beanpublic MultipartResolver multipartResolver() {return new StandardServletMultipartResolver();}
}

ok,现在项目重新启动后,在上面的checkResolver()方法里打断点,这时发现multipartResolver有值了,说明装配成功了。但是令人意外的是,断点执行到Controller层的uploadFile接口,发现入参file还是null。

WHAT THE FUCK!

终极排查——源码分析

既然我手动装配这个解析器没用,那说明Spring不认我手动装配的这个解析器。
不过转过头来一想,讲道理MultipartResolver解析器是不需要手动装配的,只要配置文件里配了spring.servlet.multipart.enabled=true,这个解析器就能在项目启动的时候被装配才对。
所以,这里我想的是,还是要解决MultipartResolver没有自动装配的问题。
事已至此,只能去看MultipartAutoConfiguration的源码了。
在这里插入图片描述
从源码可以看到,
MultipartAutoConfiguration装配的三个条件:
1.容器中有Servlet、StandardServletMultipartResolver、MultipartConfigElement
2.配置文件spring.servlet.multipart.enabled: true
3.应用启动的类型是SERVLET类型

MultipartConfigElement装配的条件是只要Spring容器内不存在MultipartConfigElement的Bean
StandardServletMultipartResolver装配的条件是只要Spring容器内不存在MultipartResolver的Bean
Servlet肯定也是有的,不然容器都不可能起来;
因此条件1是满足的; 而条件2和条件3显然也是满足的。
奇怪了。
既然自动装配的条件都满足,为什么自动装配没装成功?
这个时候我发现:项目里存在多个版本的Spring-boot-autoconfigure依赖。
明白了,十有八九是不同版本的Spring-boot-autoconfigure冲突导致的。

还有高手?

兴致冲冲地把项目里很多依赖的版本都统一了一下,确保子模块都是用的父pom里声明的版本号,并且maven也reload了好几遍,结果:他妈的Controller的file参数还是null。

实在无语,再次回到MultipartAutoConfiguration的源码。

ctrl+鼠标左键,看看这个MultipartAutoConfiguration在哪些地方被用到了。
在调用链中看到了令人气愤的一幕:原来MultipartAutoConfiguration在另一个Controller中被排掉了。
而在此之前,我老早已经检查过模块的启动类中有没有排掉MultipartAutoConfiguration,确认没有被排掉。不过怎么也没有想到有人竟会把排除自动装配类放在Controller层里,而不放在启动类里。简直了。
在这里插入图片描述

解决

把上图的exclude=MultipartAutoConfiguration.class 去掉,uploadFile接口就能正常接收file入参了。
归根结底还是历史遗留问题。

http://www.dtcms.com/a/331057.html

相关文章:

  • 题解:P4777 【模板】扩展中国剩余定理(EXCRT)
  • Qt项目查找依赖库打包
  • IDEA、Pycharm、DataGrip等激活破解冲突问题解决方案之一
  • Springboot项目重启后Session依旧存在
  • Python包性能优化与并发编程:构建高性能应用的核心技术(续)
  • 轻量级开源全文搜索引擎:Manticore Search 入门介绍
  • C++基础(①入门教程)
  • 本地jar导入到本地仓科和远程仓库
  • Maven学习笔记
  • 92、23种设计模式-单例模式
  • 项目日志框架与jar中日志框架冲突 解决
  • 《多级缓存架构设计与实现全解析》
  • 自动化测试|持续集成Git使用详解
  • label studio 服务器端打开+xshell端口转发设置
  • 01数据结构-最短路径Dijkstra
  • 【数据结构入门】
  • 移动机器人底盘在高校科研中的AI智能教育应用
  • (第十五期)HTML文本格式化标签详解:让文字更有表现力
  • Flutter GetX 全面指南:状态管理、路由与依赖注入的最佳实践
  • SpringMVC请求与响应
  • 三坐标测量仪:从机械精密到智能协同的技术
  • flutter 开发 鸿蒙 App
  • gitee_配置自动部署vue项目
  • Uniapp 获取系统信息:uni.getSystemInfo 与 uni.getSystemInfoSync
  • vs2022 opencv环境配置(使用相对地址-将依赖都放入项目中)
  • spring boot配置es
  • 开发避坑指南(26):Vue3 input输入框前置后 置元素解决方案
  • 新增和编辑共用弹窗模板
  • .Net Core控制台程序连接HGDB并部署到Linux
  • 【C#】跨平台创建你的WinForms窗体应用(WindowsUbuntu)