【问题标题】:Spring 3 -- form with 2 buttons, sending 2 parameters to controller methodSpring 3 -- 带有 2 个按钮的表单,向控制器方法发送 2 个参数
【发布时间】:2013-05-13 03:37:10
【问题描述】:

我有一个带有 2 个参数的 Spring 3 MVC 表单,我正试图将其发送到我的控制器方法,但出现 404 错误。这个问题的转折是表单有 2 个提交按钮,单击的提交按钮决定了其中一个参数的值。这是我的表格。

    <form:form action="/approve/${bulletin.id}" method="post">
        <table>
            <tr>
                <td colspan="2"><b>From:</b> <c:out value="${bulletin.name}" /></td>
            </tr>
            <tr>
                <td colspan="2"><b>Subject:</b> <c:out
                        value="${bulletin.subject}" /></td>
            </tr>
            <tr>
                <td colspan="2"><b>Date:</b> <c:out value="${bulletin.date}" />
                    <br></td>
            </tr>
            <tr>
                <td colspan="2"><t:notePrint note="${bulletin.note}" /> <input
                    type="hidden" name="id" value="${bulletin.id}" /></td>
            </tr>
            <tr>
                <td><input type="submit" name="approve" value="Approve" /></td>
                <td><input type="submit" name="deny" value="Deny" /></td>
            </tr>
        </table>
        <br />
    </form:form>

这是我的控制器表单。

@RequestMapping(value = "/approve/{id}", method = RequestMethod.POST)
public String approveBulletin(@RequestParam int id,
        @RequestParam(required = false, value = "approve") String approve,
        @RequestParam(required = false, value = "deny") String deny, Model model) {
    try {
        if (approve.equalsIgnoreCase("approve")) {
            bulletinDAO.approveBulletin(id);
            model.addAttribute("approval",
                    "Your bulletin has been approved.");
        }
        if (deny.equalsIgnoreCase("deny")) {
            bulletinDAO.denyBulletin(id);
            model.addAttribute("approval", "Your bulletin has been denied.");
        }

        List<Bulletin> bulletins = bulletinDAO.getApprovedBulletins();
        model.addAttribute("bulletins", bulletins);
    } catch (Exception e) {
        System.out.println(e.getMessage());
        return "FailurePage";
    }

    return "ApproveBulletin";
}

【问题讨论】:

    标签: spring-mvc submit http-status-code-404 parameter-passing


    【解决方案1】:

    我已经解决了我自己的问题。我发布我的代码是为了让遇到同样问题的其他人受益。这是我的表格。

    <form:form action="approve" method="post">
        <table>
            <tr>
                <td colspan="2"><b>From:</b> <c:out value="${bulletin.name}" /></td>
            </tr>
            <tr>
                <td colspan="2"><b>Subject:</b> <c:out
                        value="${bulletin.subject}" /></td>
            </tr>
            <tr>
                <td colspan="2"><b>Date:</b> <c:out value="${bulletin.date}" />
                    <br></td>
            </tr>
            <tr>
                <td colspan="2"><t:notePrint note="${bulletin.note}" /> <input
                    type="hidden" name="id" value="${bulletin.id}" /></td>
            </tr>
            <tr>
                <td><input type="submit" name="approve" value="Approve" /></td>
                <td><input type="submit" name="deny" value="Deny" /></td>
            </tr>
        </table>
        <br />
    </form:form>
    

    这是我的控制器方法。

    @RequestMapping(value = "/approve", method = RequestMethod.POST, params = { "approve" })
    public String approve(@RequestParam int id, @RequestParam String approve, Model model) {
        try {
            bulletinDAO.approveBulletin(id);
            model.addAttribute("approval", "Your bulletin has been approved.");
    
            List<Bulletin> bulletins = bulletinDAO.getApprovedBulletins();
            model.addAttribute("bulletins", bulletins);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return "FailurePage";
        }
    
        return "ApproveBulletin";
    }
    
    @RequestMapping(value = "/approve", method = RequestMethod.POST, params = { "deny" })
    public String deny(@RequestParam int id, @RequestParam String deny, Model model) {
        try {
            bulletinDAO.denyBulletin(id);
            model.addAttribute("approval", "Your bulletin has been denied.");
    
            List<Bulletin> bulletins = bulletinDAO.getApprovedBulletins();
            model.addAttribute("bulletins", bulletins);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return "FailurePage";
        }
    
        return "ApproveBulletin";
    }
    

    【讨论】:

    • 如何使用 MockMVC 进行测试?
    • 这没有用 MockMVC 测试。这是使用 Tomcat 中的应用程序测试的,因为用户通常会使用它。
    【解决方案2】:

    您的表单的action 设置为"/approve",但您的控制器映射为"/approve/{action}/{id}"; Dispatcher Servlet 无法在这两者之间建立连接。

    即使方法正确映射,它也不会做你期望它做的事情:你混淆了actioninput以及它们在HTTP请求中对应的内容。

    action 设置表单请求的 URL,在您的情况下是“/approve”。 每个&lt;input&gt; 元素的name 参数用于添加值为value 的HTTP 参数,因此请求将具有以下组合:

    • id=${id}(所有请求)
    • approve=Approve(如果用户点击“批准”)
    • deny=Deny(如果用户点击“拒绝”)

    要处理这两种情况,控制器的签名应更改为以下内容:

    @RequestMapping(value = "/approve", method = RequestMethod.POST)
    public String approveBulletin(@RequestParam int id,
                @RequestParam(required=false, defaultValue="") String approve,
                @RequestParam(required=false, defaultValue="") String deny,
                Model model) {
        if (approve.equals("Approve")) {
          // user clicked "approve"
        } else if (deny.equals("Deny")) {
          // user clicked "deny"            
        } else {
          throw new IllegalArgumentException("Need either approve or deny!");
        }
    
        // (...)
    }
    

    但我更建议更改提交按钮的参数:

    <td><input type="submit" name="approveParam" value="approveVal" /></td>
    <td><input type="submit" name="approveParam" value="denyVal" /></td>
    

    这样你总能得到两个参数:idapprove,然后你可以检查approve 的值,看看它是“批准”还是“拒绝”:

    public String approveBulletin(@RequestParam int id,
            @RequestParam(value = "approveParam") String approveOrDeny,
            Model model) {
        if (approveOrDeny.equalsIgnoreCase("approveVal")) {
            // user clicked "approve"
        } else if (approveOrDeny.equalsIgnoreCase("denyVal")) {
            // user clicked "deny"
        } else {
            // wrong parameter sent
        }
    

    帮助诊断此类问题(即是客户端问题还是服务器问题)的方法是使用浏览器的 Web 工具(Firefox 中的 Firebug、Chrome 中的开发者工具等)检查传出请求。您可以轻松捕获请求并查看 HTTP 参数、URL 和方法是什么,并将它们与您的期望进行比较。

    【讨论】:

    • 根据您的建议,我已使用最新版本的代码更新了我的原始帖子。现在正在传递 id,但不是我单击的按钮的值。
    • 能否确认在请求中是否可以看到“approve”或“deny”参数? (使用您的浏览器工具)我刚刚在一个简化的表单上进行了测试,它正确地发送了按钮的值。
    • 我刚刚在Firebug中找到了这个参数。在 Net / All / Post 下,我看到:id=%25%7Bid%7D&approve=Approve。我应该如何重写代码?
    • 应该正确处理批准/拒绝部分,您必须将 JSP 中的 "%{id}" 更改为 "${id}" 以用实际整数 ID 替换此占位符。更新了我的答案以包含另一个建议选项的代码示例。
    • 我已按照您的建议进行操作,但仍然出现 404 错误。在 Firebug 中,在 Net / All / Post 下,我注意到在参数部分中,它在 id 之前列出了批准,但我想知道它是否只是按字母顺序列出它们。在 Source 部分,它仍然给我与上面相同的垃圾,id=%25%7Bid%7D&approve=Approve。我猜它是在字符串“id”周围加上花括号,而不是没有任何花括号的实际id(一个int)。有关如何纠正此问题的任何 ID?垃圾字符串的参数顺序正确。
    猜你喜欢
    • 2018-05-24
    • 2016-06-25
    • 2016-05-14
    • 1970-01-01
    • 2016-01-12
    • 1970-01-01
    • 2019-11-29
    • 1970-01-01
    • 2023-03-06
    相关资源
    最近更新 更多