Spring MVC在Tomcat 6.0.35上使用@RequestParam和RequestMethod.DELETE

时间:2012-06-12 09:41:08

标签: spring spring-mvc http-delete

我有一个简单的方法(在Tomcat 6.0.35上运行),如下所示:

@RequestMapping(value = "/bla/d", method = RequestMethod.DELETE)
@ResponseStatus(HttpStatus.NO_CONTENT)
public void d(@RequestParam String d){
    //logic here
}

当我发送带有类似参数的帖子的DELETE请求(d = gggg在正文中)时,我收到400 Bad Request。 但如果我把它改成

@RequestMapping(value = "/bla/d", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.NO_CONTENT)
public void d(@RequestParam String d){
    //logic here
}

完美无缺。 我正在使用Firefox附加组件来测试它(以及python和Spring的RestTemplate,结果相同)这里的请求是如何看待POST的(a是一个带有参数a的cope粘贴方法):

POST /bla/a HTTP/1.1
Host: ~~~~:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 7
Pragma: no-cache
Cache-Control: no-cache
a=asdas

HTTP/1.1 204 No Content
Server: Apache-Coyote/1.1
Date: Tue, 12 Jun 2012 09:29:46 GMT

删除看起来像:

DELETE /bla/d HTTP/1.1
Host: ~~~~~:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 7
d=asdas

HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 971
Date: Tue, 12 Jun 2012 09:30:04 GMT
Connection: close

请帮助我,我可能会遗漏一些愚蠢的东西,但我无法看到它。 我最初的问题是通过DELETE请求通过类似邮件的主体发送数组,但似乎更基本的东西是错误的。

3 个答案:

答案 0 :(得分:15)

经过一些研究和调试后,我发现Spring的ServletWebREquest调用了org.apache.catalina.connector.RequestFacade.getParameterValues的getParameterValues,它调用了getParameterValues,其中我找到了以下行(Request.java 2599- 2600):

if (!getMethod().equalsIgnoreCase("POST"))
return;

这会杀死任何尝试使用DELETE发送类似POST的参数,这意味着Tomcat会主动限制此用例,即使RFC does not restrict such usage(虽然它确实说某些现有实现可能会拒绝此类请求,但Tomcat只是抛出它的参数)。 是什么让一个人使用Spring和Tomcat并尝试将带有参数的DELETE请求发送给丑陋的解决方案,例如使用@RequestBody获取所有请求体并手动提取它,这使得您想要删除某些地图的某些地方的无辜方法包含请求正文。

@fmucar

答案 1 :(得分:0)

我遇到了类似的问题,我发现的解决方案是在查询字符串中添加字段。我仍然想知道以这种方式排除表单正文的原因,但是现在这是一个解决方法。

因此,对于您的示例,这将意味着添加     ?A = asdas 主持人:~~~~~:8080网址。

我正在使用spring-webmvc:3.2.4.RELEASE所以我不确定这是否适用于您的版本。

答案 2 :(得分:0)

这是一篇非常古老的帖子,但是如果其他人正在寻找如何在DELETE方法上启用@RequestParam,这就是我在tomcat 8.5.4上所做的。

@Value("${server.parseBodyMethods}")
private String parseBodyMethods;

@Bean
public TomcatEmbeddedServletContainerFactory containerFactory() {
    return new TomcatEmbeddedServletContainerFactory() {
        protected void customizeConnector(Connector connector) {
            super.customizeConnector(connector);
            connector.setParseBodyMethods(parseBodyMethods);
        }
    };
}

插入' POST,DELETE'到该自定义程序,您的删除请求参数应该开始工作。

我在org.apache.catalina.connector.Connector中找到了parseBodyMethods,这里有Tomcat的文档:

  

这在希望支持PUT请求的POST样式语义的RESTful应用程序中非常有用。请注意,除POST之外的任何设置都会导致Tomcat的行为方式违反servlet规范的意图。这里根据HTTP规范明确禁止HTTP方法TRACE。默认为POST(Source