@PostMapping vs @DeleteMapping"必需字符串参数' name'不存在"

时间:2018-05-24 14:56:43

标签: spring-mvc spring-boot

我正在使用REST客户端进行测试。我使用完全相同的查询,只需将方法从POST更改为DELETE。我在Spring Boot 2.0.1中使用相同的方法 - 只需将注释从@PostMapping更改为@DeleteMapping

@DeleteMapping(value = "/receiver")
public ResponseEntity<Response> doOperation(@RequestParam(value = "name") String name) {
    return new ResponseEntity<>(HttpStatus.OK);
}

一旦我更改为DELETE,我就会收到错误:

"Required String parameter 'name' is not present"

我已经用@PutMapping测试了它 - 也可以。

我做错了什么?

更新1

删除请求:

DELETE /api/v1/wud/receiver?action=something HTTP/1.1
Cookie: PHPSESSID=e6b750be296f28174196817f126b367a
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: somehost:9443
Connection: close
User-Agent: Paw/3.1.7 (Macintosh; OS X/10.13.4) GCDHTTPRequest
Content-Length: 10

name=ASDEF

响应提到错误

POST请求:

POST /api/v1/wud/receiver?action=something HTTP/1.1
Cookie: PHPSESSID=e6b750be296f28174196817f126b367a
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: somehost:9443
Connection: close
User-Agent: Paw/3.1.7 (Macintosh; OS X/10.13.4) GCDHTTPRequest
Content-Length: 10

name=ASDEF

回复是200

更新2

我能够使用原始的spring示例gs-rest-service在非常简单的设置中重现它。我已经在github HERE上分享了它.MockMvc测试通过时很有意思,但它在现实中并没有起作用。

我将用Spring启动填充错误

3 个答案:

答案 0 :(得分:2)

这不是Spring的问题,但嵌入式tomcat本身作为DELETE请求的主体通常会被忽略。

这是一种解决方法。

对于spring-boot 2.0 +,

@Configuration
public class TomcatConfig implements TomcatConnectorCustomizer
{

    @Override
    public void customize(Connector connector) {
        connector.setParseBodyMethods("POST,PUT,DELETE");
    }
}

可以在spring-boot 1.5+中完成,如下所示。

@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
    return new TomcatEmbeddedServletContainerFactory(){
        @Override
        protected void customizeConnector(Connector connector) {
            super.customizeConnector(connector);
            connector.setParseBodyMethods("POST,PUT,DELETE");
        }
    };
}

但这是一种不好的做法。因为您最终执行了POST,但将其称为DELETE api。

答案 1 :(得分:2)

不应该使用DELETE请求发送有效负载。 DELETE请求就像rm命令,您要求服务器删除资源。

发送有效负载未定义,可能因服务器而异

来自RFC:

A payload within a DELETE request message has no defined semantics;
sending a payload body on a DELETE request might cause some existing
implementations to reject the request.

来源:https://tools.ietf.org/html/rfc7231#section-4.3.5

答案 2 :(得分:1)

从您的问题来看,您似乎正在@RequestBody使用@PostMapping,而是使用@DeleteMapping @RequestParam。{/ p>

此外,您正在使用请求正文而不是url参数调用DELETE api。根据您的请求信息,我看到:

DELETE /api/v1/wud/receiver?action=something HTTP/1.1

但你必须像这样调用你的删除API:

DELETE /api/v1/wud/receiver?action=something&name=something
                              Here ---------^^^^^

使用curl,您可以使用:

curl -X DELETE '{{url}}/api/v1/wud/receiver?action=something&name=something'

另一方面,如果name param不是必需的,那么您可以使用:

@RequestParam(value = "name", required = false) String name