你好,我对@ModelAttribute批注有疑问。据我了解,我们在方法参数中使用@ModelAttribute从模型中获取数据。但是,很难清楚地了解其使用时间和方式。 (代码示例摘自Spring in Action 5书) 为什么在这种情况下,在以下代码中,公共字符串processOrder()方法中,我们不对 @有效订单
使用@ModelAttribute批注 @Controller
@RequestMapping("/orders")
@SessionAttributes("order")
public class OrderController {
private OrderRepository orderRepo;
public OrderController(OrderRepository orderRepo) {
this.orderRepo = orderRepo;
}
@GetMapping("/current")
public String orderForm(@AuthenticationPrincipal User user,
@ModelAttribute Order order) {
if (order.getDeliveryName() == null) {
order.setDeliveryName(user.getFullname());
}
//following conditions
return "orderForm";
}
@PostMapping
public String processOrder(@Valid Order order, Errors errors, // <<< Here
SessionStatus sessionStatus,
@AuthenticationPrincipal User user) {
if (errors.hasErrors()) {
return "orderForm";
}
order.setUser(user);
orderRepo.save(order);
sessionStatus.setComplete();
return "redirect:/";
}
}
但是在这种情况下,在@Valid Taco taco上使用方法 processDesign()上的DesignTacoController类@ModelAttribute:
@Slf4j
@Controller
@RequestMapping("/design")
public class DesignTacoController {
@PostMapping
public String processDesign(@Valid @ModelAttribute("design") Taco design, // <<< Here
Errors errors, Model model) {
if (errors.hasErrors()) {
return "design";
}
// Save the taco design...
// We'll do this in chapter 3
log.info("Processing design: " + design);
return "redirect:/orders/current";
}
然后在下一章中,作者从同一DesignTacoController类的 processDesign()方法中删除@ModelAttribute。
@Controller
@RequestMapping("/design")
@SessionAttributes("order")
@Slf4j
public class DesignTacoController {
@ModelAttribute(name = "order")
public Order order() {
return new Order();
}
@ModelAttribute(name = "design")
public Taco design() {
return new Taco();
}
@PostMapping
public String processDesign(
@Valid Taco taco, Errors errors, // <<< Here
@ModelAttribute Order order) {
log.info(" --- Saving taco");
if (errors.hasErrors()) {
return "design";
}
Taco saved = tacoRepo.save(taco);
order.addDesign(saved);
return "redirect:/orders/current";
}
在此代码段中(来自上面的代码):
@PostMapping
public String processDesign(
@Valid Taco taco, Errors errors, // <<< Here
@ModelAttribute Order order) {
....
}
书中的引用:“ Order参数用@ModelAttribute注释,以指示其 值应该来自模型,并且Spring MVC不应尝试绑定 向其请求参数。” 我不明白作者在这里的意思,因为在所有教程中都说@ModelAttribute用作方法参数时,它将请求参数绑定到它。将表单数据与POJO bean绑定,然后使用来自提交表单的数据填充模型属性。
答案 0 :(得分:1)
文档对此非常清楚:
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-methods
@ModelAttribute
用于访问模型中的现有属性(如果没有,则实例化 当前)并应用了数据绑定和验证。参见@ModelAttribute 以及Model和DataBinder。
请注意,使用@ModelAttribute是可选的(例如,设置其 属性)。请参阅此表末尾的“其他任何参数”。
。
其他任何论点
如果方法参数与以下任何早期值都不匹配 此表,它是一个简单的类型(由 BeanUtils#isSimpleProperty,它被解析为@RequestParam。 否则,将其解析为@ModelAttribute 。
因此从本质上讲它是可选的。您可能希望仅使用它来明确表明要解决该参数,或者如果不应该进行绑定,则可能需要使用(通过指定binding = false
),请参见:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ModelAttribute.html。通常,无论如何我都倾向于指定它。
答案 1 :(得分:0)
我也不清楚。
在这里,我们需要指定模型属性的名称。 因为我们认为我们将其命名为“ design”而不是“ taco”。
@PostMapping
public String processDesign(@Valid @ModelAttribute("design") Taco design, Errors errors) {
如果我们将Taco类重命名为Design ...
如果模型属性,我们不需要指定名称。
它将从类的简单名称推导出来。
com.example.Design
-> "design"
@PostMapping
public String processDesign(@Valid Design design, Errors errors) {
请参见javadoc for ModelAttribute:
默认模型属性名称是从声明的 属性类型(即方法参数类型或方法返回类型), 根据不合格的类别名称:例如类的“ orderAddress” “ mypackage.OrderAddress”或“ orderAddressList” “列表”。