【发布时间】:2021-03-17 12:38:27
【问题描述】:
我对 thymeleaf 形式的帖子有疑问。它发生在我试图将我的 ShoppingCart 对象发送到控制器时。 项目详情: 有 /products 端点,用户可以在其中将所需的产品添加到他的 ShoppingCart(session)。 在购物车中,添加的产品将转换为具有字段产品和数量的新实体 OrderedProduct。 当用户准备好时,他会去 /cart 端点确认交易并发送订单。
所以,然后我将发布请求发送到 /orders 端点。但是在控制器中,我得到了一个带有空字段(orderedProducts,total)的空购物车。 据我了解,这是百里香的预期行为。为了从我的购物车中传递参数,我应该明确地将它们定义为表单中的隐藏字段。 所以我添加了这个:
<input type="hidden" name="total" th:field="*{total}"/>
<input type="hidden" name="orderedProducts" th:field="*{orderedProducts}"/>
然后我得到这样的异常:
Field error in object 'shoppingCart' on field 'orderedProducts': rejected value [null,null];
codes [typeMismatch.shoppingCart.orderedProducts,typeMismatch.orderedProducts,typeMismatch.java.util.List,typeMismatch];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [shoppingCart.orderedProducts,orderedProducts];arguments [];
default message [orderedProducts]];default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.List' for property 'orderedProducts';
nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Long] for value 'null,null';
nested exception is java.lang.NumberFormatException: For input string: "null,null"]]
据我了解这是转换问题,我们应该为 OrderedProduct 定义特殊转换器(如本主题中:https://stackoverflow.com/a/60066445/14308420)。 考虑到 OrderedProduct 存储在 session 中,但没有 id,如何制作转换器?
checkout.html
<form th:action="@{/orders}" th:object="${cart}" method="post">
<input type="hidden" name="total" th:field="*{total}"/>
<input type="hidden" name="orderedProducts" th:field="*{orderedProducts}"/>
<label for="phoneNumber">Phone number: </label>
<input type="number" required="required" name="phoneNumber"
class="form-control" id="phoneNumber">
<button type="submit" class="btn-lg btn-primary">Order</button>
</form>
OrderUIController
@PostMapping
public String create(@ModelAttribute ShoppingCart cart,
@RequestParam("phoneNumber") Long phoneNumber) {
Order order = new Order();
order.setOrderedProducts(cart.getOrderedProducts());
order.setPhoneNumber(phoneNumber);
order.setTotal(cart.getTotal());
service.create(order);
return "redirect:/profile";
}
购物车
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ShoppingCart implements Serializable {
private List<OrderedProduct> orderedProducts = new ArrayList<>();
private Long total;
}
OrderedProduct
public class OrderedProduct extends AbstractBaseEntity {
private Integer quantity;
private Product product;
}
【问题讨论】:
-
与您的问题没有直接关系,但您不应从隐藏字段中的值中获取
total。如果有人打开 devtools 并更改那里的价值,他们将能够非常便宜地购物。 -
@WimDeblauwe 感谢您的重要评论。我们如何才能确保字段总数?考虑到用户可以在 checkout.html 中更改购物车中产品的数量,并且字段总计将相应更改。 我想警告:在您的个人资料中“驯服 Thymeleaf”和“使用 Spring Boot 构建 API 后端的实用指南”指向相同的链接。
-
感谢关于我的个人资料的提示,现已修复。关于总数:您应该让服务器根据购物车中的产品再次计算总数。您可以从
Order中删除setTotal,并让该类根据订单上设置的产品计算它。
标签: html spring spring-mvc thymeleaf