0

这就是现在的样子:

@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 对象时,它将由其默认构造函数初始化。您认为做出该决定的原因是什么?

4

1 回答 1

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.
}
于 2013-11-10T17:14:33.767 回答