我是否必须分离wicket模型,如果它们用于局部变量?

时间:2011-07-31 18:09:46

标签: java wicket

我在我的wicket应用程序中使用PropertyModel和Compoundpropertymodel。我将它们用作局部变量而不是页面类的成员。我是否必须覆盖onDetach()函数以在模型本地时分离它们?或者只是成员变量序列化到会话中?

示例:

TextField<String> title = new TextField<String>("title", new PropertyModel<String>(position, "title"));
title.setRequired(true);
form.add(positionTitle);

3 个答案:

答案 0 :(得分:3)

我不清楚为什么要分离TextField的模型,因为TextField需要一个模型对象来写入提交的表单值。如果从PropertyModel中分离position,则TextField将无法在用户提交表单后将其“title”值写入。您可能希望提供有关position是什么,从何处加载以及在请求周期之间需要分离的原因的更多详细信息。通常的做法是为表单组件设置一个安全可序列化的模型对象,以便将其值写入。

如果确实需要在每个请求结束时分离PropertyModel的模型对象,请将PropertyModel链接到LoadableDetachableModel。 LDM将根据您提供的load()方法为每个请求周期加载一个新的模型对象,然后在分离时自动将其对该模型对象的引用置空,以防止序列化模型对象。如果使用LoadableDetachableModel<Position>作为PropertyModel的模型对象,则PropertyModel将自动分离LoadableDetachableModel,这足以避免序列化position对象。

请注意,您不需要在示例中的模型上显式调用detach(); Wicket自动分离页面层次结构中所有组件的默认模型。通过“默认模型”,我的意思是一个模型,它被传递到super(...)链并最终成为model构造函数之一的Component(...)参数。

在请求处理结束时,Page会在其子项上调用detach()(这些孩子会在其子项上调用detach(),依此类推)。此方法(在Component中定义)调用detachModels(),后者又分离组件的默认模型。

通常使用多个模型的标准Wicket组件将在detachModels期间分离其他模型。例如,如果您将DropDownChoice传递给获取/设置所选值的模型以及选择列表的模型,您会注意到DropDownChoice会在每个请求结束时自动分离这两个模型。这是因为AbstractChoice#detachModel()查找并分离choices模型(如果已设置)。

链接模型也会分离它们的链式模型,例如,如果你有

Form<User> userForm = new Form<User>("userForm", new CompoundPropertyModel<User>(new DetachableUserModel(...));

然后,detachModels将自动分离CompoundPropertyModel,这将分离DetachableUserModel。

如果你需要担心手动分离模型,你可以在代码中使用既不是某个组件的默认model,也不会链接到另一个模型的其他模型。如果要创建具有多个模型对象的新类型的组件,这可能是一个问题。

答案 1 :(得分:2)

在这个例子中,在Wicket中大多数使用这种模型时,初始赋值是局部变量,但是对象被放入 not local的东西中。

您的form几乎肯定是一个字段或包含在某个内容中,并被序列化到会话中。它包含title字段,后者又包含模型。

所以它会被序列化,是的,你应该实现onDetach()

修改

正如评论中所指出的,真正重要的是它是否是页面的组件层次结构的一部分,而不是它是否是一个字段。它在某种程度上相同,因为页面的子组件或任何其他组件都保存在超类children的字段org.apache.wicket.MarkupContainer中。

答案 2 :(得分:1)

在你的情况下,我会这样做:

    IModel model = new CompoundPropertyModel(new LoadableDetachableModel(position){
        @Override protected Object load() { return null; }
    });
    Form form = new Form("form", model);
    form.add(
            new TextField("title")
                .setRequired(true));
    add(form);

在请求结束时在链中调用detach()。使用LoadableDetachableModel确保未引用位置对象。

技巧:保持域对象或值对象不可序列化。在开发配置中,如果您有序列化错误,则意味着您保留对这些对象的引用。