我是 Spring 的新手,正在阅读“Spring in Action”(这确实是一本好书)。 在这里,我在本书的一个示例中遇到了一个问题,让我很困惑。 在这个example中,有两个控制器分别对应两条路径。一个是 DesignTacoController,另一个是 OrderController。
在我自己试用这个例子的过程中,我首先复制了 OrderController,它是一个非常简单的类,如下所示。当网页上有/没有错误输入时,这段代码可以完美运行。
@Slf4j
@Controller
@RequestMapping("/orders")
public class OrderController {
@GetMapping("/current")
public String orderForm(Model model) {
model.addAttribute("order", new Order());
return "orderForm";
}
@PostMapping
public String processOrder(@Valid Order order, Errors errors) {
if (errors.hasErrors()) {
return "orderForm";
}
log.info("Order submitted: " + order);
return "redirect:/";
}
}
然后我根据上面的OrderController自己实现了DesignTacoController
@Slf4j
@Controller
@RequestMapping("/design")
public class DesignTacoController {
@GetMapping
public String showDesignForm(Model model) {
List<Ingredient> ingredients = Arrays.asList(
// adding some ingredients
);
Type[] types = Ingredient.Type.values();
for (Type type: types) {
model.addAttribute(
type.toString().toLowerCase(Locale.ROOT),
filterByType(ingredients, type));
}
model.addAttribute("design", new Taco());
return "design";
}
@PostMapping
public String processDesign(@Valid Taco design, Errors errors) {
if (errors.hasErrors()) {
return "design";
}
log.info("Processing design: " + design);
return "redirect:/orders/current";
}
// more methods ignored
}
有了这个实现,当没有错误输入时它可以正常工作。但是,如果我针对验证器输入一些内容,我会得到一个
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'design' available as request attribute
通过在stackoverflow(this question)上搜索并查看github上的original example code,我发现这个类应该是这样实现的
@Slf4j
@Controller
@RequestMapping("/design")
public class DesignTacoController {
@ModelAttribute
public void addIngredientsToModel(Model model) {
List<Ingredient> ingredients = Arrays.asList(
// adding some ingredients
);
Type[] types = Ingredient.Type.values();
for (Type type : types) {
model.addAttribute(type.toString().toLowerCase(),
filterByType(ingredients, type));
}
}
@GetMapping
public String showDesignForm(Model model) {
model.addAttribute("design", new Taco());
return "design";
}
@PostMapping
public String processDesign(@Valid @ModelAttribute("design") Taco design, 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";
}
// more methods ignored
}
我的问题来了,
我觉得我缺少一些Spring的基本概念。希望有人能帮我解决这个问题。
非常感谢。
答案 0 :(得分:1)
在方法级别使用@ModelAttribute 的目的是向模型添加一个或多个模型属性。在这里添加这个
到模型。 model.addAttribute(type.toString().toLowerCase(), filterByType(ingredients, type)); }
事情是 Spring 在任何请求映射之前创建模型对象。所以 addIngredientsToModel 方法将在任何 Handler 方法之前被调用。