【问题标题】:Spring MVC - How do I call the same URL with different mapping annotationsSpring MVC - 如何使用不同的映射注释调用相同的 URL
【发布时间】:2019-06-26 18:03:15
【问题描述】:

我用两种方法设置了一个控制器。 URL 映射完全相同,唯一的区别是映射注释方法。一个是@PostMapping,另一个是按该顺序编写的@DeleteMapping。但是,当我尝试调用@DeleteMapping 方法时,会调用@PostMapping 方法。

请注意,尽管两种 URL 形式中的变量不同,但它们的值相同。它们只是来自不同的 HTML 页面。

问题是如何每次调用所需的方法。

@PostMapping 方法

@Secured({"ROLE_ADMIN", "ROLE_STUDENT"})
@PostMapping("students/{username}/internships/{id}")
public String addInternship(Model model, @PathVariable("username") String username, @PathVariable("id") int id) {

    /* DOES SOME STUFF
    Student student = userService.getUser(username).getStudent();
    Internship internship = userService.getInternship(id);

    StudentInternship studentInternship = new StudentInternship(internship, student, "Sent");

    internship.setNumberOfPositions(internship.getNumberOfPositions() - 1);
    userService.updateInternship(internship);

    student.setApplicationNumber(student.getApplicationNumber() + 1);
    userService.updateStudent(student);

    userService.addStudentInternship(studentInternship);
    */

    return "redirect:/internships";
}

@DeleteMapping 方法

@Secured({"ROLE_ADMIN", "ROLE_STUDENT"})
@DeleteMapping("students/{username}/internships/{id}")
public String removeInternship(Model model, @PathVariable("username") String username, @PathVariable("id") int id) {

    /* DOES SOME STUFF
    Student student = userService.getUser(username).getStudent();
    Internship internship = userService.getInternship(id);

    int studentInternshipID = userService.getStudentInternshipByParams(student, internship).getId();

    internship.setNumberOfPositions(internship.getNumberOfPositions() + 1);
    userService.updateInternship(internship);

    student.setApplicationNumber(student.getApplicationNumber() - 1);
    userService.updateStudent(student);

    userService.removeStudentInternship(studentInternshipID);
    */

    return "redirect:/students/" + username + "/internships";
}

HTML

<form:form action="${pageContext.request.contextPath}/students/${username}/internships/${tempInternship.id}" method="POST">
    <input type="submit" value="Request" ${disabled}/>
</form:form>

<form:form action="${pageContext.request.contextPath}/students/${tempStudentInternship.student.username}/internships/${tempStudentInternship.internship.id}" method="DELETE">
    <input type="submit" value="Dismiss" />
</form:form>

【问题讨论】:

    标签: java html hibernate spring-mvc jakarta-ee


    【解决方案1】:

    浏览器仅支持GETPOST 作为http 请求方法。解决方案是使用POST 方法发送您的表单,并在名为_method 的同一个html 表单中注入一个隐藏字段,并使用您想要的方法作为值,在您的情况下,它只是DELETE。对于POST 的情况,照常写表单即可。

    示例:

    <form:form action="${pageContext.request.contextPath}/students/${tempStudentInternship.student.username}/internships/${tempStudentInternship.internship.id}" method="POST">
        <input type="hidden" name="_method" value="DELETE"/>
        <input type="submit" value="Dismiss" />
    </form:form>
    

    请查看this answer 以创建spring bean,然后在spring:form html 表单中应用提到的表单属性。

    【讨论】:

    • 你没有说的是它依赖于框架并且不是开箱即用的。所以他仍然需要一些东西来实际完成这项工作,而这个东西再次以包含 javascript 的形式出现:)
    • 是的,OP 已经在 Spring MVC 中开发应用程序,并且有一个内置的 servlet 过滤器拦截这个特殊的表单属性_method,用它的值替换请求动词。
    【解决方案2】:

    仅允许来自 FORM 的 GET 和 POST。您需要使用 AJAX 来指定请求的其他类型。 您好,您需要使用 javascript 和 XMLHttpRequest 来指定请求的类型。

    这是我从网上随机取的一个例子:

    // Delete a user
    var url = "http://localhost:8080/api/v1/users";
    var xhr = new XMLHttpRequest();
    xhr.open("DELETE", url+'/12', true);
    xhr.onload = function () {
        var users = JSON.parse(xhr.responseText);
        if (xhr.readyState == 4 && xhr.status == "200") {
            console.table(users);
        } else {
            console.error(users);
        }
    }
    xhr.send(null);
    

    【讨论】:

    • 问题是我不想使用 Javascript。我读到我使用的 Spring 标签支持这些额外的方法,但我并不完全理解它们,所以我想知道我是否可以以某种方式进行。
    • HTML 5 不支持表单方法 DELETE。您需要找出 HTML 5 和 javascript 的替代方法。祝你好运:)
    • 对了,下面HPH同事贴的解决方案也是javascript,只是你不会直接调用。如果不包含支持方法覆盖的适当 javascript 框架,它将无法开箱即用。
    • @AlexandarPetrov,我认为您在这里遗漏了一点,拦截_method表单属性的spring MVC servlet过滤器在服务器端,我的解决方案中没有javascript东西(直接或间接使用) .
    • @HPH 我没有错过重点 :) 关键是,如果是 Spring MVC 或 JQuery 或 Playframework,则在某处独立存在第三方框架,可确保将 _method 转换为 Delete。提出请求。这不是开箱即用的功能。拦截器是在浏览器中还是在 servlet 容器中,这很重要吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2021-01-26
    相关资源
    最近更新 更多