简体   繁体   English

Spring MVC @ModelAttribute @SessionAttributes-为什么模型属性需要带@ModelAttribute注释的方法?

[英]Spring MVC @ModelAttribute @SessionAttributes - Why does a model attribute need a @ModelAttribute annotated method?

This is how it all looks now: 这就是现在的样子:

@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;
    }
}

When the addToCart method is called first time, the shoppingCart object will be initialized by the createShoppingCart method. 首次调用addToCart方法时,将由createShoppingCart方法初始化shoppingCart对象。 After the addToCart method runs, the initialized object will be added to the session and it will be used from the session for the later use. addToCart方法运行后,已初始化的对象将添加到会话中,并将在会话中使用该对象以供以后使用。 That means the createShoppingCart methode is called just once (as long as it does not removed from the session). 这意味着createShoppingCart方法仅被调用一次(只要它没有从会话中删除)。

Why does Spring eliminate the need for the ModelAttribute annotated initializer method, by simply creating this object whenever is needed? 为什么Spring仅通过在需要时创建该对象,从而消除了对ModelAttribute带注释的初始化方法的需要? Then it would all look simpler like this: 然后,看起来会更简单:

@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;
    }
}

Whenever the shoppingCart object will not be found in the session, it would be initialized by its default constructor.. What do you think the reason is for that decision? 每当在会话中找不到shoppingCart对象时,都会通过其默认构造函数对其进行初始化。您认为该决定的原因是什么?

I can't speak directly for the Spring team, but your suggestion would limit the desired ModelAttribute to a newly created instance on each request (prior to being stored in the session,) but what if you wanted to start with a fully populated object, say, fetched from a datastore? 我无法直接代表Spring团队,但是您的建议是将所需的ModelAttribute限制为每个请求(在存储在会话中之前)一个新创建的实例,但是如果您想从一个完全填充的对象开始,比如说,是从数据存储区中获取的? Your method offers no way to do that. 您的方法无法做到这一点。 This, however, works well: 但是,这很好用:

@ModelAttribute
public ShoppingCart createShoppingCart() {
    ...
    return someShoppingCartRepo.find(...);
}

This, of course, is just one possible scenario where the usefulness of a separate method should be evident. 当然,这只是一种可能的情况,在这种情况下,应使用单独的方法来证明其有效性。

EDIT AFTER COMMENTS 编辑后的评论

You could easily create your own HandlerMethodArgumentResolver that would give you a new instance of your object if none existed, but it might be overkill considering how easy it is to use your createShoppingCart() method. 您可以轻松地创建自己的HandlerMethodArgumentResolver ,如果不存在该对象,它将为您提供对象的新实例,但是考虑到使用createShoppingCart()方法有多么容易,这可能会过大。 If you are using xml configs, it would be something like this: 如果您使用的是xml配置,则将如下所示:

<mvc:annotation-driven ...>
    <mvc:argument-resolvers>
        <bean class="yourpackage.YourCustomArgumentResolver" />
    </mvc:argument-resolvers>
</mvc:annotation-driven>

You could extend any number of existing HandlerMethodArgumentResolver base classes, or you could implement the interface directly yourself, but most likely you would use something like this: 您可以扩展任何数量的现有HandlerMethodArgumentResolver基类,或者您可以自己直接实现接口,但是最有可能的是使用以下代码:

public class YourCustomArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
    // Implement/override methods for creating your model object when encountered as a method argument
}

To identify your argument, you could create a custom annotation: 为了确定您的论点,您可以创建一个自定义注释:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface YourAutoCreateModelAttribute {

    String value() default "";

    boolean required() default true;

    String defaultValue() default ValueConstants.DEFAULT_NONE;
}

Then annotate your method like this to kick off your custom resolver: 然后像这样注释您的方法以启动您的自定义解析器:

@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.
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在@ModelAttribute注释方法中返回Spring模型 - Returning a Spring Model in a @ModelAttribute annotated method Spring MVC3 @SessionAttributes和@ModelAttribute将自动从请求中获取值 - Spring MVC3 @SessionAttributes and @ModelAttribute will automatically get value from request @ModelAttribute在方法签名中使用@ModelAttribute注释方法 - @ModelAttribute annotated method WITH @ModelAttribute in method signature 为什么在 Spring MVC 3.0 中使用 @ModelAttribute 'update()' 不重定向到 'sox'? - Why does 'update()' not redirect to 'sox' using @ModelAttribute in Spring MVC 3.0? 通过带注释的@ModelAttribute方法将Spring Controller方法从模型绑定中排除 - Exclude Spring Controller method from model binding through annotated @ModelAttribute method 无法在Spring MVC中更新以@ModelAttribute注释的对象 - Can't update object which annotated with @ModelAttribute in Spring MVC Spring MVC第二个Post方法@ModelAttribute为null - Spring MVC second Post method @ModelAttribute is null Spring MVC中方法级别的@ModelAttribute声明 - @ModelAttribute declaration at a method level in Spring MVC Spring 3 MVC:@ModelAttribute方法+ @Autowired无法正常工作 - Spring 3 MVC: @ModelAttribute method + @Autowired not working Spring MVC @ModelAttribute 作为方法参数注解 - Spring MVC @ModelAttribute as a method parameter annotation
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM