Spring MVC可以使用HTTP PUT方法的请求参数吗?还是必须使用POST方法?为了符合RESTful,我应该使用哪种方法?

20

我有一个控制器操作,我认为应该是HTTP PUT请求,但当我在控制器操作中尝试使用@RequestParam时,Spring发出了警告。请求参数不允许用于HTTP PUT方法吗?这就是为什么Spring会拒绝它的原因吗?

@RequestMapping(value = "/{helpDocumentId}/vote", method = RequestMethod.PUT)
public void voteHelpfulness(@PathVariable long helpDocumentId, @RequestParam boolean isHelpful) {
    helpManager.voteOnHelpDocument(helpDocumentId, isHelpful);
}

执行时,会抛出以下错误:

org.springframework.web.bind.MissingServletRequestParameterException: Required boolean parameter 'isHelpful' is not present

当然,isHelpful 参数是存在的。我可以让上面的代码在HTTP POST中完美运行,所以我知道这不是问题所在。

     $.ajax({
            url: "/help/" + helpDocumentId + "/vote.json",
            type: "PUT",
            data: {
                isHelpful: isHelpful
            },
            success: function(response) {
                // ....
            }
     });

PUT是正确的HTTP方法吗?这个操作修改了helpDocument,但它并没有创建一个新的helpDocument


5
这是一个关于Spring框架中的问题追踪页面(Jira)。具体内容以英文呈现,请提供更具体的翻译需求。 - digitaljoel
@digitaljoel,虽然有点晚了,但是从Spring 3.1开始就有了HttpPutFormContentFilter - Arjan
@Arjan 很好知道。我只需将数据作为 JSON 放在请求体中,并使用 RequestBody 注释处理它。不需要任何过滤器,它就可以正常工作™。 - digitaljoel
嗯,@digitaljoel,当使用正确的 @RequestBody 类型时,它会“Just Works™”;-)(刚刚看到试图处理传入 JSON 时出现问题,使用了 @RequestBody MultiValueMap<String, String>。) - Arjan
哦,@digitaljoel,也许Spring/Jackson可以将JSON映射到(嵌套的)MultiValueMap。如果你知道的话,请看这里的评论(https://dev59.com/LG3Xa4cB1Zd3GeqPjNIL#1Y_jnYgBc1ULPQZFkuLX)。你是映射到自定义类型、纯字符串还是通用类型? - Arjan
显示剩余3条评论
4个回答

15

Spring 3.1以来,HttpPutFormContentFilter 可以用于处理 application/x-www-form-urlencoded 数据:

该过滤器使表单编码数据在 HTTP PUT 请求期间通过 ServletRequest.getParameter*() 方法系列可用。

Servlet 规范要求在HTTP POST请求中必须可用表单数据,但不需要在 HTTP PUT 请求中。该过滤器拦截 HTTP PUT 请求,并读取其中的表单编码内容,如果请求的内容类型为 'application/x-www-form-urlencoded' ,则将 ServletRequest 封装起来,以使表单数据像 HTTP POST 请求一样可用作请求参数。

对于其他传入的数据,例如JSON,您需要使用@RequestBody,如JQuery,Spring MVC @RequestBody和JSON-使其一起工作中所解释的那样,以避免出现415 Unsupported Media Type错误。

6

Spring控制器支持GET/HEAD/POST/PUT/DELETE/OPTIONS/TRACE等请求方法,但是由于您的浏览器可能无法发送这些请求方法,因此它对您不起作用。

解决方法是使用Spring提供的"org.springframework.web.filter.HiddenHttpMethodFilter"。它要求您传递一个用于请求方法的隐藏参数。该过滤器支持的默认参数为"_method"。

有关更多信息,请查看该过滤器的javadoc。


3

如前所述,这似乎是spring/servlet API中的一个错误。实际上,PUT请求应该在请求主体(或负载)而不是请求参数上工作。从这个意义上说,servlet API和Spring的处理是正确的。

话虽如此,更好、更简单的解决方法是从你的javascript/jQuery调用中不传递数据元素,并将你的参数作为url的一部分传递。也就是说,在url字段中设置参数的方式与GET调用相同。

$.ajax({
            url: "/help/" + helpDocumentId + "/vote.json" + "?param1=param2Val&..",
            type: "PUT",
            data: "",
            success: function(response) {
                // ....
            }
     });

现在,这适用于简单的参数,但我猜对于复杂的JSON类型不起作用。希望这可以帮助到你。


0

我按照评论中的建议将@RequestParam更改为@RequestBody,它就起作用了(我的参数是一个字符串)。

我同意这是Spring中的一个bug,因为在本地主机上使用@RequestParam时失败的完全相同的代码在生产环境中却可以正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接