前言
在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>
然后重启服务就可以在修改时做图片上传啦!