9

我有一个带有 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";
}
4

2 回答 2

15

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

<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";
}
于 2013-05-18T04:32:43.250 回答
10

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

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

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

  • 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 中的 Firebugs、Chrome 中的开发人员工具等)检查传出请求。您可以轻松捕获请求并查看 HTTP 参数、URL 和方法是什么,并将它们与您的期望进行比较。

于 2013-05-13T09:15:21.150 回答