http content type的含义和Springweb PUT方法支持
常见表单提交格式
先从可以看到的地方说起,postman是一个很好用的工具,
form-data,是提交form表单的标准选项之一,如果html form标签没有指定enctype,那么默认使用这种方式提交表单,内容格式如下:
{boundary}
Content-Disposition: form-data; name={direct name}
{value}
...<loop line1 to line4>...
{boundary}--
header中content-type应该指定multipart/form-data; boundary={boundary}
x-www-form-urlencoded,是提交form表单的标准选项之一,形式是
{encoded_name1}={encoded_value1}&{encoded_name2}={encoded_value2}
客户端的name和value都是字符串,然后encode之后拼接添加到http request的entity。发送。
raw,不是http协议的一种content-type,只是postman的称呼而已,用户为了提供entity数据给server而不是为了提交form表单。表单是一种特殊含义的数据,一般都是name value对,而提交数据的含义则广泛得多,例如elasticsearch查询时候需要提供json作为entity,但是并不要求把json作为value,与一个name关联,从而形成一个form表单提交。
在postman中raw的用法就可以是:
{"query":"...."}
header中增加Content-Type: application/json
或者当提交xml的时候也可以是:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
">
<bean id="xxx" ...>
</beans>
header中添加Content-Type:text/xml。
强调
html的form控件只能用multipart/form-data或者application/x-www-form-urlencoded,因此form标签做不到application/json或者text/xml提交。
Ajax可以更灵活,发送json content-type的entity
Spring 对PUT的支持
Browsers can submit form data via HTTP GET or HTTP POST. Non-browser clients can also submit forms via HTTP PUT. This presents a challenge because the Servlet specification requires the ServletRequest.getParameter*() family of methods to support form field access only for HTTP POST, not for HTTP PUT.To support HTTP PUT and PATCH requests, the spring-web module provides the filter HttpPutFormContentFilter, which can be configured in web.xml:
<filter>
<filter-name>httpPutFormFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>httpPutFormFilter</filter-name>
<servlet-name>dispatcherServlet</servlet-name>
</filter-mapping>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
The above filter intercepts HTTP PUT and PATCH requests with content type application/x-www-form-urlencoded, reads the form data from the body of the request, and wraps the ServletRequest in order to make the form data available through the ServletRequest.getParameter() family of methods.
可知,servlet规范规定,只有POST方法可以getParameter,PUT,DELETE都不行,更不要说GET了。
网上提到的Tomcat的DefaultServlet的readonly问题与这个不同。DefaultServlet是提供静态资源访问和list目录的servlet,该servlet有自己的配置,默认不接受PUT和DELETE方法的请求。由于tomcat开箱即提供静态资源访问的能力,后端就是依赖这个DefaultServlet。如果只使用了DefaultServlet的情况下,会拒绝一些PUT和DELETE方法,因为一般通过浏览器访问静态资源是不会有这种方法的。