springmvc 4.3 的项目升级到springboot2.6 自定义字段解密Filter导致文件上传可能失败的问题解决
20250826
问题背景
- springmvc 4.3 的项目升级到springboot2.6
- 文件解析器用的是:CommonsMultipartResolver, 不过是继承自 CommonsMultipartResolver 做了一些缓存 和匹配过程
- 写了个filter 用户解密前端的字段中的加密部分 然后在这个filter中判断是文件数上传的时候 就 先执行文件解析器的动作 获取的Multipart request 做requesWrapper (这里做的字段解密工作)
- 这个filter在原来的项目中是能工作的 升级后 当是文件上传的时候 在controller就接收不到这个文件字段了 报错了
- 当前项目CommonsMultipartResolver 指定的name为MultipartFilter.DEFAULT_MULTIPART_RESOLVER_BEAN_NAME=”filterMultipartResolver”;
springboot升级造成的 一些变化
1. CommonsMultipartResolver vs StandardServletMultipartResolver 的区别
- CommonsMultipartResolver
- 依赖
Apache Commons FileUpload
库。 - 通过 Commons 的解析逻辑将
HttpServletRequest
包装成 MultipartHttpServletRequest
。 - 在 SpringMVC 时代(Spring 3.x、4.x),这是常见方案。
- StandardServletMultipartResolver
- 基于 Servlet 3.0+ 标准 API (
javax.servlet.http.Part
)。 - 不依赖 Commons-FileUpload,直接利用容器(Tomcat/Jetty)的
multipart-config
。 - 在 Spring Boot 里默认使用这个(除非你主动注册
CommonsMultipartResolver
)。
升级到 Spring Boot 2.6 后,默认不再用 CommonsMultipartResolver
,而是走 StandardServletMultipartResolver
。这会影响 Filter 的执行顺序、Request 包装时机。
2. Spring Boot 2.6 的文件上传处理模式
Spring Boot 的设计目标是 零配置、依赖 Servlet 3.0+。
- 默认不再用
MultipartFilter
,而是完全走 DispatcherServlet 模式。 - Spring Boot 自动配置了一个
StandardServletMultipartResolver
,利用 Servlet 3.0 标准 API (request.getParts()
) 解析上传。 - 所以:
- 默认的 Bean 名是
multipartResolver
。 - 类型是
StandardServletMultipartResolver
(不是 Commons)。
这样就完全不需要再配 MultipartFilter
了。
升级后失效的原因
文件流重复解析:
我认为主要是启用了MultipartFilter, 导致文件解析提前,导致原来的字段解密Filter中的手动调用文件解析器再次解析无法获取到文件流 从而最终进入controller的时候为null.
修改方案
方案一: 禁用MultipartFilter (当前采用)
- 去掉MultipartFilter
- 修改文件解析器的bean name 修改为DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME
验证成功
方案二: 不禁用MultipartFilter,保证文件解析器只处理一次
- 考虑让MultipartFilter 先执行
- 在自定义Filter中不判断已经解析,则强转
MultipartHttpServletRequest
后再Wrapper解密
尚未验证