HTTP状态码405 - 请求方法'POST'不支持(Spring MVC)

26

我遇到了这个错误:HTTP Status 405 - Request method 'POST' not supported

我的目标是创建一个表单,其中一个下拉框的值基于另一个下拉框中所选择的值填充。例如,当我在customerName下拉框中选择一个名称时,在.jsp页面中的onChange函数应该运行,并且页面将被提交,然后以相应的值在customerCountry下拉框中重新加载。

但是,我遇到了这个HTTP状态405错误。我已经在互联网上搜索了解决方案,但没有找到有用的信息。以下是代码的相关部分:

.jsp页面的一部分

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Insert title here</title>
            <style>
            .error { color: red; }
            </style>

        <script>
            function repopulate(){  
                document.deliveryForm.submit();
            }

            function setFalse(){
                document.getElementById("hasId").value ="false";
                document.deliveryForm.submit();
                // document.submitForm.submit(); (This was causing the error)

            }
        </script>

    </head>
    <body>

        <h1>Create New Delivery</h1>

        <c:url var="saveUrl" value="/test/delivery/add" />
        <form:form modelAttribute="deliveryDtoAttribute" method="POST" action="${saveUrl}" name="deliveryForm">
            <table>


                <tr>
                    <td><form:hidden id="hasId" path="hasCustomerName" value="true"/></td>
                </tr>

                <tr>
                    <td>Customer Name</td>
                    <td><form:select path="customerName" onChange="repopulate()">
                        <form:option value="" label="--- Select ---" />
                        <form:options items="${customerNameList}" />
                        </form:select>
                    </td>
                    <td><form:errors path="customerName" cssClass="error" /></td>
                </tr>

                <tr>
                    <td>Customer Country</td>
                    <td><form:select path="customerCountry">
                        <form:option value="" label="--- Select ---" />
                        <form:options items="${customerCountryList}" />
                        </form:select>
                    </td>
                    <td><form:errors path="customerCountry" cssClass="error" /></td>
                </tr>

        </form:form>

        <form:form name="submitForm">
        <input type="button" value="Save" onClick="setFalse()"/>
        </form:form>

    </body>
</html>

控制器的一部分:

@RequestMapping(value = "/add", method = RequestMethod.GET)
    public String getDelivery(ModelMap model) {
        DeliveryDto deliveryDto = new DeliveryDto();

        model.addAttribute("deliveryDtoAttribute", deliveryDto);
        model.addAttribute("customerNameList",
                customerService.listAllCustomerNames());
        model.addAttribute("customerCountryList", customerService
                    .listAllCustomerCountries(deliveryDto.getCustomerName()));
        return "new-delivery";
    }

    // I want to enter this method if hasId=true which means that a value in the CustomerName 
    // drop down list was selected. This should set the CountryList to the corresponding values 
    // from the database. I want this post method to be triggered by the onChange in the jsp page

    @RequestMapping(value = "/add", method = RequestMethod.POST, params="hasCustomerName=true")
    public String postDelivery(
            @ModelAttribute("deliveryDtoAttribute") DeliveryDto deliveryDto,
            BindingResult result, ModelMap model) {


            model.addAttribute("deliveryDtoAttribute", deliveryDto);

            model.addAttribute("customerNameList",
                    customerService.listAllCustomerNames());
            model.addAttribute("customerCountryList", customerService
                    .listAllCustomerCountries(deliveryDto.getCustomerName()));

            return "new-delivery";
    }

    // This next post method should only be entered if the save button is hit in the jsp page

    @RequestMapping(value = "/add", method = RequestMethod.POST, params="hasCustomerName=false")
    public String postDelivery2(
            @ModelAttribute("deliveryDtoAttribute") @Valid DeliveryDto deliveryDto,
            BindingResult result, ModelMap model) {

        if (result.hasErrors()) {

            model.addAttribute("deliveryDtoAttribute", deliveryDto);

            model.addAttribute("customerNameList",
                    customerService.listAllCustomerNames());
            model.addAttribute("customerCountryList", customerService
                    .listAllCustomerCountries(deliveryDto.getCustomerName()));

            return "new-delivery";
        } else {

            Delivery delivery = new Delivery();

            //Setters to set delivery values

            return "redirect:/mis/home";
        }

    }

为什么我会收到这个错误?非常感谢任何帮助!谢谢。

编辑:hasId 更改为 hasCustomerName。但我仍然收到 HTTP状态405 - 不支持请求方法 'POST' 的错误信息。

编辑2:setFalse 函数中注释掉导致错误的那一行代码。

// D


4
为什么会被投反对票?请给我一个解释,这样我以后能够发布更好的问题。谢谢。 - dlinx90
针对遇到此问题并访问本页面的人,请确保定义的操作命中了一个现有的端点,这可能是我的问题的原因 :) - Andrei Epure is hiring
7个回答

23

我不确定这是否有帮助,但我曾经遇到同样的问题。

您正在使用具有CSRF保护的springSecurityFilterChain。这意味着在发送POST请求时必须发送一个令牌。尝试向您的表单中添加下一个输入:

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

如何暂时禁用此过滤器链?因为有很多更改方法,我希望它首先能够正常工作,然后逐步升级。 - Yu Jiaao
@YuJiaao - 你可以在Spring Security参考文档的第18.4.2章节中找到它。https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html#csrf-configure - Andrei Epure is hiring

19

检查您是否返回@ResponseBody或@ResponseStatus

我遇到了类似的问题。我的控制器代码如下:

@RequestMapping(value="/user", method = RequestMethod.POST)
public String updateUser(@RequestBody User user){
    return userService.updateUser(user).getId();
}

当使用POST请求时,我总是遇到以下错误:

HTTP状态405 - 不支持的请求方法“POST”

过了一会儿,我发现实际上方法被调用了,但由于没有@ResponseBody和@ResponseStatus,Spring MVC就会引发错误。

要解决此问题,只需添加@ResponseBody即可。

@RequestMapping(value="/user", method = RequestMethod.POST)
public @ResponseBody String updateUser(@RequestBody User user){
    return userService.updateUser(user).getId();
}

或者在您的方法上添加 @ResponseStatus。

@RequestMapping(value="/user", method = RequestMethod.POST)
@ResponseStatus(value=HttpStatus.OK)
public String updateUser(@RequestBody User user){
    return userService.updateUser(user).getId();
}

5
你可能需要更改这行代码。
@RequestMapping(value = "/add", method = RequestMethod.GET)

to

@RequestMapping(value = "/add", method = {RequestMethod.GET,RequestMethod.POST})

3
不,有两种方法,每种都对应一个RequestMethod。 - Jacob Mattison

4
问题在于您的控制器需要一个参数hasId=falsehasId=true,但您没有传递该参数。您的隐藏字段具有id hasId,但被传递为hasCustomerName,因此没有匹配项。
要么将隐藏字段的路径更改为hasId,要么将映射参数更改为期望hasCustomerName=truehasCustomerName=false

我看到我写这个时有点累了。眼力真好!但我仍然遇到完全相同的错误。你有什么想法吗? - dlinx90
1
为什么错误信息如此误导?它让我们认为这是一个HTTP动词问题,而实际上是参数问题。 - Stephane

3

我发现了导致HTTP错误的问题。

在由保存按钮触发的setFalse()函数中,我的代码试图提交包含该按钮的表单。

        function setFalse(){
            document.getElementById("hasId").value ="false";
            document.deliveryForm.submit();
            document.submitForm.submit();

当我移除了 document.submitForm.submit(); 这行代码,它就能正常工作:
        function setFalse(){
            document.getElementById("hasId").value ="false";
            document.deliveryForm.submit()

@Roger Lindsjö,感谢您发现了我的错误,我没有传递正确的参数!


1
在我的情况下,URL 以 / 结尾。 paymentUrl(旧)= /get-details/
我只是删除了末尾的 / paymentUrl(新)= /get-details
然后它就可以工作了。

移除 @RequestMapping(value="/user" 中的尾部斜杠,这样就可以正常工作了!我猜应该与调用者匹配。 - Karthik Rao

0

我遇到了类似的问题,但原因不同(url模式test-response未添加在csrf令牌中),我通过在config/local.properties文件中的以下属性中允许我的URL模式来解决它:

csrf.allowed.url.patterns = /[^/]+(/[^?])+(sop-response)$,/[^/]+(/[^?])+(merchant_callback)$,/[^/]+(/[^?])+(hop-response)$

修改为

csrf.allowed.url.patterns = /[^/]+(/[^?])+(sop-response)$,/[^/]+(/[^?])+(merchant_callback)$,/[^/]+(/[^?])+(hop-response)$,/[^/]+(/[^?])+(test-response)$


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