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 メソッドは (セッションから削除されない限り) 1 回だけ呼び出されます。

必要なときにいつでもこのオブジェクトを作成するだけで、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(...);
}

もちろん、これは別の方法の有用性が明らかになるシナリオの 1 つにすぎません。

コメント後に編集

オブジェクトが存在しない場合にオブジェクトの新しいインスタンスを提供する独自のインスタンスを簡単に作成できますが、メソッド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 に答える