org.springframework.web.HttpRequestMethodNotSupportedException DELETE请求被拒绝

时间:2017-08-08 08:36:28

标签: java spring rest xmlhttprequest http-delete

无法加载资源:服务器响应状态为405。

我在f-secure和赫尔辛基大学的在线课程上学习。我通过了测试,但在@CrossOrigin之后我无法让服务器接受删除请求(originins =" / **")。 该应用程序是一个简单的任务列表,其中表单接受输入并创建列表元素。该应用程序还将输入作为对象存储在另一个页面/ tasks中。当我想删除它们时,/ tasks不会让我失望。 html文件中的http.send给出了错误。如何让服务器接受我的删除请求? 一些有趣的说明;无论我在何处发送删除请求,都会收到相同的错误。它可能也是4140i2t0efsk.org。同样的错误。 CORS已启用。

Chrome控制台错误:

(index):112 DELETE http://localhost:8080/(random id) 405 ()

XHR failed loading: DELETE "http://localhost:8080/(same random id).

TaskController.java

    package sec.controller;

    import java.util.ArrayList;
    import java.util.List;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;

    import org.springframework.web.bind.annotation.RestController;
    import sec.domain.Task;


    @RestController
    @CrossOrigin(origins = "/**")
    @RequestMapping("/tasks")
    public class TaskController {

    private List<Task> tasks;

    public TaskController() {
        this.tasks = new ArrayList<>();
        Task fixme = new Task();
        fixme.setName("A random task.");
        this.tasks.add(fixme);
    }

    @RequestMapping(method = RequestMethod.GET)
    public List<Task> list() {
        return this.tasks;
    }   


    @RequestMapping(method = RequestMethod.POST)
    public Task add(@RequestBody Task task) {
        this.tasks.add(task);
        return task;
    }


    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public Task delete(@PathVariable String id) {
        Task t = this.tasks.stream().filter(task -> task.getId().equals(id)).findFirst().get();
        this.tasks.remove(t);
        return t;
    }
    }'

参见tasks.html

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
    <head lang="en">
        <meta charset="UTF-8" />
        <title>Tasks</title>
    </head>
    <body>

        <h2>Tasks</h2>
        <a href="http://127.0.0.1:8080/tasks">Existing tasks</a>
        <!-- TODO: add the ability to list tasks -->
        <ul id="tasks">
        </ul>


        <form>
            <input type="text" name="name" id="name"/>
            <input type="button" onclick="addTask()" value="Add!"/>
        </form>

        <!-- the javascript has been embedded to the same site -->
        <script th:inline="javascript">

            var url = null;

            function loadTasks() {
              console.log("Requesting XML HTTP");
              var http = new XMLHttpRequest();
              http.onreadystatechange = function() {
                  if (http.readyState == 4) {
                      console.log("***READY");
                      if (http.status == 200) {
                          console.log("***STATUS OK");
                          var response = JSON.parse(http.responseText); 
                          console.log("***RESPONSE ", response); // object
                          console.log("***TYPE HTTP RESPONSE", typeof(http.response));
                          console.log("***TYPE RESPONSE", typeof(response));
                          console.log("***HTTP RESPONSE ", http.response); //string
                          console.log("***FOR EACH...");
                          response.forEach(addTaskToList);

                      };
                  } 

             }; 
              http.open("GET", "/tasks", true);
              http.send(null); 
            }

            function addTask() {
                var name = document.querySelector("#name").value;
                if (!name) {
                    return;
                }

                console.log("**NAME ",name, );

                var http = new XMLHttpRequest();
                http.open("POST", url, true);
                http.setRequestHeader("Content-type", "application/json");
                var data = new Object();
                data.name = name;

                http.onreadystatechange = function () {
                    if (http.readyState === 4) {
                        if (http.status === 200) {
                            addTaskToList(JSON.parse(http.responseText));
                        }
                    }
                };

                http.send(JSON.stringify(data));
            }


            function addTaskToList(task) {
                var liElement = document.createElement("li");
                liElement.id = task.id;
                console.log("***Element id: ", task.id);
                console.log("***Element type:", typeof(liElement));
                liElement.appendChild(document.createTextNode(task.name));
                liElement.addEventListener("click", function(){removeTask(task.id);});
                document.querySelector("#tasks").appendChild(liElement);

            }


            function removeTask(task_id) {
                console.log("***REMOVE TASK: ", task_id);
                document.getElementById(task_id).innerHTML = "Removing...";
                document.getElementById(task_id).remove();

                var http = new XMLHttpRequest();

                http.open("DELETE", "/"+(String(task_id)), true);
                http.setRequestHeader("Content-type", "application/json");
                http.onload = function() {
                    tasks = JSON.parse(http.responseText);
                    if (http.readState == 4) {
                        if (http.status == 200) {
                            console.table(tasks);
                            }
                        else {
                            console.error(tasks);
                        }
                    }
                };
                http.send(String(task_id)); //*** HERE IS THE ERROR ***
            }

    window.onload = function () {
                loadTasks();
            };
        </script>
    </body>
</html>

Task.java

package sec.domain;

import java.util.UUID;

public class Task {

    private String id;
    private String name;

    public Task() {
        this.id = UUID.randomUUID().toString();
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                            http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>sec</groupId>
    <artifactId>S201.Tasks</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>    

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.1.RELEASE</version>
    </parent>



    <dependencies>   
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>

        <!-- TMC -->
        <dependency>
            <groupId>fi.helsinki.cs.tmc</groupId>
            <artifactId>edu-test-utils</artifactId>
            <version>0.4.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>tmc</id>
            <name>TMC repo</name>
            <url>http://maven.testmycode.net/nexus/content/groups/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>tmc</id>
            <name>TMC repo</name>
            <url>http://maven.testmycode.net/nexus/content/groups/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
</project>

2 个答案:

答案 0 :(得分:1)

    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public Task delete(@PathVariable("id") String id) {
        Task t = this.tasks.stream().filter(task -> task.getId().equals(id)).findFirst().get();
        this.tasks.remove(t);
        return t;
    }

尝试添加方法标题("id")

顺便问一下,有没有WebSecurityConfig类?你也可以分享它。

答案 1 :(得分:1)

解决方案

问题在于映射。 正如您在代码中看到的,我将DELETE请求发送到/ {id}。由于我尝试删除的对象驻留在localhost:8080 / tasks中,我应该将DELETE请求发送到/ tasks / {id}。

感谢您的帮助。我花了几天时间才弄清楚一个简单的问题。