400 客户端发送的请求语法错误

400 the request sent by the client was syntactically incorrect

我已经研究了很多这种性质的示例并从该站点提出了解决方案,但是其中 none 提供的解决方案适用于我的问题。我相信这个错误消息 400 会在发送到控制器的信息被格式化时出现。我花了最后两天交叉引用我过去从事的另一个项目,该项目有效,但我无法解决问题。

@RequestMapping(value = {"/", "/home"}, method = RequestMethod.GET)
    public String homePage(ModelMap model) {
       model.addAttribute("user", getPrincipal());
    Catalog catalog = catalogService.getCatalogByCategory(Catalog.CatalogCategory.ALL);

    model.addAttribute("catalog", catalog);
    return "welcome";
}

这会将数据发送到我的 JSP 上的 JSTL Spring 表单,如下所示:

<form:form method="POST" modelAttribute="catalog">
        <form:hidden path="id"/>
        <form:hidden path="name"/>
        <form:hidden path="category"/>
        <form:hidden path="orderItems"/>


        <div id="products" class="row list-group">
            <c:forEach var="orderItem" items="${catalog.orderItems}">

                <div class="item  col-xs-4 col-lg-4">
                    <div class="thumbnail">
                        <img class="group list-group-image" src="http://placehold.it/400x250/000/fff" alt=""/>

                        <div class="caption">
                            <h4 class="group inner list-group-item-heading">
                                    ${orderItem.name}</h4>

                            <p class="group inner list-group-item-text">
                                    ${orderItem.description}
                            </p>

                            <div class="row">
                                <div class="col-xs-12 col-md-6">
                                    <p class="lead">
                                        R ${orderItem.price}</p>
                                </div>
                                <div class="col-xs-12 col-md-6">
                                    <label for="${orderItem.id}" class="btn btn-primary">Add to Cart <input
                                            type="checkbox" id="${orderItem.id}" name="orderItem.addedToCart"
                                            class="badgebox"><span class="badge">&check;</span></label>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </c:forEach>
        </div>

        <div class="row">
            <div class="form-group">
                <div class="col-sm-12 pull-right">
                </div>
                <div class="col-sm-2 pull-right">

                    <input type="submit"
                           class="btn btn-default btn-block btn-primary"
                           value="Next" name="action" formmethod="POST"
                           formaction="confirmList"/>

                </div>
            </div>
        </div>
    </form:form>`

此时我将表单提交给控制器中的以下侦听器:

@RequestMapping(value = "/confirmList", method = RequestMethod.POST)
public String confirmList(@ModelAttribute Catalog catalog, @ModelAttribute     String numberOfItemsAdded) {

     List<OrderItem> selectedItems = new ArrayList<OrderItem>();
    for (OrderItem orderItem : catalog.getOrderItems()) {
        if (orderItem.isAddedToCart()) {
            selectedItems.add(orderItem);
        }
    }
    //model.addAttribute("numberOfItemsAdded", selectedItems.size());
    return "welcome";
}

就是这样,执行流程甚至没有返回我的控制器。令人筋疲力尽的错误,因为我真的不明白我在这里做错了什么。提前谢谢你

编辑:

Catalog.java

 @Entity
 @Table(name="Catalogs")
 public class Catalog{

 private long id; //generated value using hibernate ...
 private String name; //column annotated by @Column
 private String category;// column also annotated by @Column
 private List<OrderItem> orderItems;// one to many mapping

  //getters and setters here
}

在你的控制器中尝试这个额外的句柄并检查你的控制台,

@ExceptionHandler(MissingServletRequestParameterException.class)
public void handleMissingRequestParams(MissingServletRequestParameterException ex) {
    System.out.println();
    System.out.println("------------------------MissingServletRequestParameterException------------------------");
    System.out.println("  Parameter name:-    "+ex.getParameterName());
    System.out.println("  Parameter Type:-    "+ex.getParameterType());
    System.out.println("  Cause:-             "+ex.getCause());
    System.out.println("  LocalizedMessage:-  "+ex.getLocalizedMessage());
    System.out.println("  Message:-           "+ex.getMessage());
    System.out.println("  RootCause:-         "+ex.getRootCause());
    System.out.println("-------------------------------********************-----------------------------");
}

编辑

@kholofelo Maloma 我在你的 jsp

中看不到变量 numberOfItemsAdded

而且我从来没有使用过 @ModelAttribute String numberOfItemsAdded 到 String 参数请在文档中检查这个,我认为它与 Bean 一起使用,请确认

宁愿使用@RequestParam

Read Documentation Here

它清除了我

抱歉上面的句柄,

Note however that reference data and all other model content is not available to web views when request processing results in an Exception since the exception could be raised at any time making the content of the model unreliable. For this reason @ExceptionHandler methods do not provide access to a Model argument.

我测试了你的代码,我也得到了 HTTP 400。问题是浏览器发送的内容与控制器方法 confirmList 所期望的不匹配:

这是我在 Chrome 的网络选项卡中看到的表单数据:

id:1
name:the catalog
category:category
orderItems:[com.eej.ssba2.model.test.catalog.OrderItem@82ea8a, com.eej.ssba2.model.test.catalog.OrderItem@f441ae, com.eej.ssba2.model.test.catalog.OrderItem@40a13, com.eej.ssba2.model.test.catalog.OrderItem@1316c95, com.eej.ssba2.model.test.catalog.OrderItem@1cfc05a, com.eej.ssba2.model.test.catalog.OrderItem@5d725c, com.eej.ssba2.model.test.catalog.OrderItem@ff32b9, com.eej.ssba2.model.test.catalog.OrderItem@5b49a4, com.eej.ssba2.model.test.catalog.OrderItem@13faf31, com.eej.ssba2.model.test.catalog.OrderItem@6d64d]
orderItem.addedToCart:on
orderItem.addedToCart:on
orderItem.addedToCart:on
orderItem.addedToCart:on
action:Next

但控制器无法理解这一点,因为 OrderItems 显示每个 OrderItem 实例的 toString() 并且 addedToCart 未绑定到 orderItems 列表的任何 orderItem。

您必须这样修改您的jsp:

<form:form method="POST" modelAttribute="catalog">
        <form:hidden path="id"/>
        <form:hidden path="name"/>
        <form:hidden path="category"/>
        <!-- form:hidden path="orderItems"/-->


        <div id="products" class="row list-group">
            <c:forEach var="orderItem" items="${catalog.orderItems}" varStatus="status">

                <div class="item  col-xs-4 col-lg-4">
                    <div class="thumbnail">
                        <img class="group list-group-image" src="http://placehold.it/400x250/000/fff" alt=""/>

                        <div class="caption">
                            <h4 class="group inner list-group-item-heading">
                                    ${orderItem.name}</h4>
                                    <form:hidden path="orderItems[${status.index}].name" />
                            <p class="group inner list-group-item-text">
                                    ${orderItem.description}
                                    <form:hidden path="orderItems[${status.index}].description" />
                            </p>

                            <div class="row">
                                <div class="col-xs-12 col-md-6">
                                    <p class="lead">
                                        R ${orderItem.price}</p>
                                        <form:hidden path="orderItems[${status.index}].price" />
                                </div>
                                <div class="col-xs-12 col-md-6">
                                    <label for="${orderItem.id}" class="btn btn-primary">Add to Cart <input
                                            type="checkbox" id="${orderItem.id}" name="catalog.orderItems[${status.index}].addedToCart"
                                            class="badgebox"><span class="badge">&check;</span></label>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </c:forEach>
        </div>

        <div class="row">
            <div class="form-group">
                <div class="col-sm-12 pull-right">
                </div>
                <div class="col-sm-2 pull-right">

                    <input type="submit"
                           class="btn btn-default btn-block btn-primary"
                           value="Next" name="action" formmethod="POST"
                           formaction="confirmList"/>

                </div>
            </div>
        </div>
    </form:form>

如果这样做,您可以在 Chrome 的网络选项卡(或您使用的浏览器)中看到消息更改。这是现在的表单数据:

id:1
name:the catalog
category:category
orderItems[0].name:OrderItemName#0
orderItems[0].description:OrderItemDesc#0
orderItems[0].price:0.0
orderItems[1].name:OrderItemName#1
orderItems[1].description:OrderItemDesc#1
orderItems[1].price:0.43645913001303904
orderItems[2].name:OrderItemName#2
orderItems[2].description:OrderItemDesc#2
orderItems[2].price:1.7151992716801088
orderItems[3].name:OrderItemName#3
orderItems[3].description:OrderItemDesc#3
orderItems[3].price:1.303683806806788
orderItems[4].name:OrderItemName#4
orderItems[4].description:OrderItemDesc#4
orderItems[4].price:2.507039003743686
orderItems[5].name:OrderItemName#5
orderItems[5].description:OrderItemDesc#5
orderItems[5].price:3.173744751378154
orderItems[6].name:OrderItemName#6
orderItems[6].description:OrderItemDesc#6
orderItems[6].price:3.183771167856446
catalog.orderItems[6].addedToCart:on
orderItems[7].name:OrderItemName#7
orderItems[7].description:OrderItemDesc#7
orderItems[7].price:6.73370053587355
catalog.orderItems[7].addedToCart:on
orderItems[8].name:OrderItemName#8
orderItems[8].description:OrderItemDesc#8
orderItems[8].price:2.0266022634803216
orderItems[9].name:OrderItemName#9
orderItems[9].description:OrderItemDesc#9
orderItems[9].price:5.251986962977732
catalog.orderItems[9].addedToCart:on
action:Next

您现在会看到 returns HTTP 200,因为请求实际上到达了您的控制器。按照建议删除控制器方法中的 @ModelAttribute

    @RequestMapping(value = "/confirmList", method = RequestMethod.POST)
    public String confirmList(Catalog catalog, String numberOfItemsAdded) {

        List<OrderItem> selectedItems = new ArrayList<OrderItem>();
        for (OrderItem orderItem : catalog.getOrderItems()) {
            if (orderItem.isAddedToCart()) {
                selectedItems.add(orderItem);
            }
        }
        //model.addAttribute("numberOfItemsAdded", selectedItems.size());
        return "catalog";
    }