400客户端发送的请求在语法上是不正确的

时间:2016-09-13 06:23:53

标签: spring spring-mvc data-binding http-status-code-400

我已经浏览了很多这种性质的示例,并提出了本网站的解决方案,但其中提供的解决方案都不适用于我的问题。我相信,当发送到控制器的信息被形成时,会显示此错误消息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
}

2 个答案:

答案 0 :(得分:1)

我测试了你的代码,我也得到了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

您现在会看到它返回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";
    }

答案 1 :(得分:-1)

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

@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字符串参数plz在文档中检查这个,我认为它与Bean一起使用,plz确认

而是使用@RequestParam

Read Documentation Here

它清除了我

对不起上面的句柄,

  

但请注意,当请求处理导致异常时,Web视图无法使用引用数据和所有其他模型内容,因为可能会在任何时候引发异常,从而使模型的内容不可靠。因此,@ ExceptionHandler方法不提供对Model参数的访问。