这就是现在的样子:
@SessionAttributes("shoppingCart")
public class ItemController {
@ModelAttribute
public ShoppingCart createShoppingCart() {
return new ShoppingCart();
}
@RequestMapping(value=RequestMappings.ADD_TO_CART + RequestMappings.PARAM_ITEM_ID, method=RequestMethod.GET)
public String addToCart(@PathVariable("itemId") Item item, @ModelAttribute ShoppingCart shoppingCart) {
if(item != null) {
shoppingCartService.addItem(shoppingCart, item);
}
return ViewNamesHolder.SHOPPING_CART;
}
}
首次调用addToCart方法时,shoppingCart对象将由createShoppingCart方法初始化。在运行addToCart方法之后,初始化的对象将被添加到会话中,并将从会话中使用它以供以后使用。这意味着createShoppingCart方法只被调用一次(只要它不从会话中删除)。
为什么Spring只需要在需要时创建这个对象,就不需要使用ModelAttribute注释的初始化方法?然后它看起来会更简单:
@SessionAttributes("shoppingCart")
public class ItemController {
@RequestMapping(value=RequestMappings.ADD_TO_CART + RequestMappings.PARAM_ITEM_ID, method=RequestMethod.GET)
public String addToCart(@PathVariable("itemId") Item item, @ModelAttribute ShoppingCart shoppingCart) {
if(item != null) {
shoppingCartService.addItem(shoppingCart, item);
}
return ViewNamesHolder.SHOPPING_CART;
}
}
每当在会话中找不到shoppingCart对象时,它将由其默认构造函数初始化。 你认为这个决定的原因是什么?
答案 0 :(得分:1)
我不能直接为Spring团队发言,但是您的建议会将所需的ModelAttribute限制为每个请求上的新创建的实例(在存储到会话之前),但是如果您想要完全开始例如,从数据存储中获取的填充对象?你的方法无法做到这一点。然而,这很有效:
@ModelAttribute
public ShoppingCart createShoppingCart() {
...
return someShoppingCartRepo.find(...);
}
当然,这只是一种可能的情况,其中单独方法的有用性应该是显而易见的。
评论后编辑
您可以轻松创建自己的HandlerMethodArgumentResolver
,如果不存在,则可以为您提供对象的新实例,但考虑到使用createShoppingCart()
方法有多容易,可能会有些过分。如果你使用xml配置,它将是这样的:
<mvc:annotation-driven ...>
<mvc:argument-resolvers>
<bean class="yourpackage.YourCustomArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
您可以扩展任意数量的现有HandlerMethodArgumentResolver
基类,或者您可以直接自己实现该接口,但很可能您会使用以下内容:
public class YourCustomArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
// Implement/override methods for creating your model object when encountered as a method argument
}
要识别您的参数,您可以创建自定义注释:
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface YourAutoCreateModelAttribute {
String value() default "";
boolean required() default true;
String defaultValue() default ValueConstants.DEFAULT_NONE;
}
然后注释您的方法,以启动您的自定义解析器:
@RequestMapping(...)
public String doStuff(@YourAutoCreateModelAttribute ShoppingCart shoppingCart, ...) {
// Now your shoppingCart will be created auto-magically if it does not exist (as long as you wrote your resolver correctly, of course.
}