SpringMVC:解决restful风格-PUT请求无法上传文件(Request method ‘POST‘ not supported)

前言

在JQuery中,我们可以进行REST ful中delete和put的请求,但是在java EE标准中,默认只有在POST请求的时候,servlet 才会通过getparameter()方法取得请求体中的相应的请求参数的数据。而PUT,delete请求的请求体中数据则默认不会被解析。

1.关于delete请求:delete请求用来从服务器上删除资源。因此我们只需要把要删除的资源的ID上传给服务器,即使是批量删除的时候,也可以通过URL传参的方式将多个id传给servlet,因此,可以满足我们的需求,可以直接发送请求。
2.关于put请求(指的是带有请求体)
2.1没有文件时:SpringMVC提供了一个将post转换为put和delete的方法,通过在web.xml中注册一个HiddenHttpMethodFilter过滤器。
2.2上传文件时:我们可以通过在web.xml中注册一个MultipartFilter,一定要在HiddenHttpMethodFilter之前。

一、问题描述
为支持restful风格请求,并且应对可能上传文件的情况,需要在配置hiddenHttpMethodFilter过滤器之前配置MultipartFilter。目的是让MultipartFilter过滤器先将带文件上传的请求,进行解析。以便hiddenHttpMethodFilter可以取到”_method”参数,转化为相应的http动作。
既然multipartFilter要进行上传文件的解析,那么必然需要MutipartResolver,那么问题发生了!
二、报错:Request method ‘POST’ not supported
配置如下:
web.xml

<!--请求方式过滤-->
<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  </filter>
<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>  

springmvc.xml

<!--配置文件上传解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"/>
        <property name="maxUploadSize" value="104857600"/>
        <property name="maxInMemorySize" value="4096"/>
    </bean>

jar包

<!-- 文件上传 -->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>

jsp

<form action="/emp/updateEmp.do" method="post" enctype="multipart/form-data">
    <input type="hidden" name="_method" value="PUT"/>
    身份证正面:<input type="file" name="file"><br>
    身份证反面:<input type="file" name="file"><br>
    <input type="submit" value="确认修改">
</form>

然后我们看源码:

@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		String paramValue = request.getParameter(this.methodParam);
		if ("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) {
			String method = paramValue.toUpperCase(Locale.ENGLISH);
			HttpServletRequest wrapper = new HttpMethodRequestWrapper(request, method);
			filterChain.doFilter(wrapper, response);
		}
		else {
			filterChain.doFilter(request, response);
		}
	}

1.this.methodParam属性被默认初始化为"_method",通过2.request.getParameter(this.methodParam);判断是put还是delete,
“POST”.equals(request.getMethod()),而且必须要求是post方式提交的,
3.然后它把request进行包装后传给下一个filter。
4.因此,我们需要在提交的时候添加一个隐藏域

<input type="hidden" name="_method" value="PUT"/>

原因

springmvc.xml是由DispatcherServlet加载的,然后生成了springmvc的上下文对象,称为子容器。 ContextLoaderListener加载的配置文件,生成的spring的上下文对象,称为父容器。 子容器可以使用父容器中定义的bean,反之则不行。 如上multipartResovler配置在springmvc.xml中,即对应的bean在子容器中,而WebApplicationContext.containsBean()在父容器中是查找不到这个bean的

解决办法

1.新建一个spring.xml(名字任意取),
2.将springmvc.xml配置的multipartResovler配置挪入在其中(spring.xml)。
3.在web.xml配置中加入MultipartFilter配置
4.重要的是要通过ContextLoaderListener来加载此文件(spring.xml),这样这个bean就在spring的容器里了,然后WebApplicationContext.containsBean()为true,就会使用你配置的解析器,而不是使用默认的了。
如下:
spring.xml

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"/>
        <property name="maxUploadSize" value="104857600"/>
        <property name="maxInMemorySize" value="4096"/>
</bean>

web.xml 注意约束

<!--监听spring主配置-->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring.xml</param-value>
</context-param>

<filter>
    <filter-name>MultipartFilter</filter-name>
    <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
    <init-param>
      <param-name>multipartResolverBeanName</param-name>
      <param-value>multipartResolver</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  </filter>
  
<filter-mapping>
    <filter-name>MultipartFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!--配置监听器:服务启动时加载spring主配置-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

然后重启服务就可以在修改时做图片上传啦!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值