在原项目中,对文件上传的处理并不是使用Spring的MultipartResolver,而是使用自定义的MultiPartFilter和HttpServletRequestWrapper结合来进行处理。
MultiPartFilter是一个定义在web.xml中的<filter>,原理是通过判断HttpServletRequest中的contentType是否包含”multipart/form-data”,若代码中包含此字符品,则表明是一个File Upload请求,就使用JakartaMultiPartRequest来对HttpServletRequest对其进行包装。
其代码如下:
public class MultiPartFilter extends GenericFilterBean {
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
String content_type = request.getContentType();
if (content_type != null && content_type.indexOf("multipart/form-data") != -1) {
JakartaMultiPartRequest jakartaMultiPartRequest = new JakartaMultiPartRequest(request,
getFilterConfig().getInitParameter("saveDir"), Integer.valueOf(
getFilterConfig().getInitParameter("maxUploadSize")).intValue());
request = jakartaMultiPartRequest;
}
filterChain.doFilter(request, servletResponse);
}
}
JakartaMultiPartRequest类继承自HttpServletRequestWrapper,在其构造方法中,我们对Request进行分析,并且保存用户上传的文件,将文件名等信息放到Request的attribute中,从而在后续的代码中可以对上传的文件进行处理。
但在后来客户进出的对产品图片处理的新需求中,因为JakartaMultiPartRequest的问题,没有办法满足我们的要求,所以考虑到使用Spring的MultipartResolver来进行上传处理,但之前的代码不能再进行改动,否则所有处理文件上传的Controller必须更改,代价很大。但如果在Spring中进行配置MultipartResolver的配置后,发现我们旧的文件上传代码都失效了,无法上传文件。
后来经过调试,发现在我们定义的MultiPartFilter中处理过上传的请求后,Spring的MultipartResolver又对其进行了上传处理,这样就导致我们之前设计在Request中的attribute全部丢失,所以我们得想办法让我们自定义的MultiPartFilter和Spring的MultipartResolver不要互相干扰。
我们需要经两步来解决此问题:
第一步:我们对自定义的MultiPartFilter进行改动,让其接受在web.xml中传入的配置参数“excludeURL”,此参数指定那些不需要JakartaMultiPartRequest类进行处理的页面URL。
boolean jump = false;
// 根据web.xml中的配置,判断当前url是否跳过此过滤器
String excludeURL = getFilterConfig().getInitParameter("excludeURL");
if (excludeURL != null && !"".equals(excludeURL)) {
if (request.getRequestURI().indexOf(excludeURL) != -1) {
jump = true;
}
}
if (!jump) {
String content_type = request.getContentType();
if (content_type != null && content_type.indexOf("multipart/form-data") != -1) {
JakartaMultiPartRequest jakartaMultiPartRequest = new JakartaMultiPartRequest(request,
getFilterConfig().getInitParameter("saveDir"), Integer.valueOf(
getFilterConfig().getInitParameter("maxUploadSize")).intValue());
request = jakartaMultiPartRequest;
}
}
filterChain.doFilter(request, servletResponse);
第二步:
经过查看org.springframework.web.multipart.commons.CommonsMultipartResolver的源代码我们发现(我们在spring中使用commons fileupload处理上传),其中有个public boolean isMultipart(HttpServletRequest request)方法,此方法控制着Spring是否对用户的Request进行文件上传处理,于是自定义一个我们自己的CommonsMultipartResolver,继承自org.springframework.web.multipart.commons.CommonsMultipartResolver,并重写其中的public boolean isMultipart(HttpServletRequest request),在方法中对当前的request进行判断,如果是一个JakartaMultiPartRequest实例,则返回false,告知Spring不需要再对当前的request进行文件上传处理;如果不是,则直接调用父类的isMultipart方法。
代码如下:
public class CommonsMultipartResolver extends org.springframework.web.multipart.commons.CommonsMultipartResolver {
/**
* {@inheritDoc}
*
* @see org.springframework.web.multipart.commons.CommonsMultipartResolver#isMultipart(javax.servlet.http.HttpServletRequest)
*/
@Override
public boolean isMultipart(HttpServletRequest request) {
if (request instanceof JakartaMultiPartRequest) {
return false;
} else {
return super.isMultipart(request);
}
}
}
当然,Spring中的配置也要使用自定义的CommonsMultipartResolver,
<bean id="multipartResolver"
class="net.ymeng.example.web.filter.CommonsMultipartResolver">
<property name="maxUploadSize"
value="20000000" />
</bean>
这样,就可以让自定义的MultiPartFilter和Spring的MultipartResolver各司其职了。
转:http://dev.ymeng.net/spring-multipartresolver-conflict.html
分享到:
相关推荐
准备MultipartResolver: 在Spring MVC中,文件上传需要一个MultipartResolver来解析上传的文件。常用的MultipartResolver实现有CommonsMultipartResolver、StandardServletMultipartResolver等。您需要在Spring配置...
spring+hibernate包冲突问题 spring+hibernate包冲突问题
在applicantContent.xml中配置了<!-- 图片文件上传功能 -->... <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 需要引入的jar
Spring Cloud Gateway中的全局异常处理不能直接用@ControllerAdvice来处理,通过跟踪异常信息的抛出,找到对应的源码,自定义一些处理逻辑来符合业务的需求。 网关都是给接口做代理转发的,后端对应的都是REST API,...
使用springcloud的负载均衡 以及网关 实现文件的上传处理参看链接 https://blog.csdn.net/zhaoyu_nb/article/details/80579918
自定义依赖注入工具类SpringUtil.java
spring的自定义标签代码工程样例,Chapter2工程
利用Spring Context上下文创建自定义对象,学习Spring的IoC容器如何使用控制反转创建一个对象,了解Spring控制反转原理
本代码使用H2内存数据库演示spring事务使用,包括编程式事务,声明式事务@Transactional使用,自定义事务事务注解实现自定义事务管理器
– SpringMVC上传文件时,需要配置MultipartResolver处理器 –> ”multipartResolver” class=”org.springframework.web.multipart.commons.CommonsMultipartResolver”> <property name=”defaultEncoding
在spring环境中通过component-scan配置处理自定义java注解
其中包括Spring核心jar包,SpringMVCjar包,Springc3p0jar包等等,堪称最完整其中包括Spring核心jar包,SpringMVCjar包,Springc3p0jar包等等,堪称最完整的Springjar包
spring自定义注解样例
spring mvc multipartResolver结合uploadify操作图片文件上传与预览
主要是讲spring自定义xml配置的扩展相关的内容,东西不算新的,都是比较基础的,想看就看一下 我也是为了搞点积分才上传的
Spring5.0自定义配置文件便签[Maven]工程可运行【spring-customize-tag】
Spring@PropertySource 配置文件自定义加密、自定义Yaml文件加载
基于SpringBoot的文件上传系统,前后端分离,单文件上传,多文件上传,大文件上传,断点续传,文件秒传,图片上传 项目经过严格测试,确保可以运行! 采用前后端分离的方式进行开发,实现了几种常用的文件上传功能...
用springMVC+velocity时,当使用自定义标签,发现自定义标签无法注入spring的其它服务类,归根源码发现,velocity的源码中有一段,有一段代码永远获取的是新实例。所以,把这个地方的源码改了,所以使用这个的时候,...
3、对spring aop认识模糊的,不清楚如何实现Java 自定义注解的 4、想看spring aop 注解实现记录系统日志并入库等 二、能学到什么 1、收获可用源码 2、能够清楚的知道如何用spring aop实现自定义注解以及注解的逻辑...