wicket

Apache Wicket Web框架的核心概念之一是模型和IModel作为其编程接口。 Wicket组件严重依赖模型,这使它们成为体系结构的重要组成部分。 Apache Wicket是一个有状态框架,将页面及其组件存储到通常位于HTTP会话中的页面存储中。 组件根据模型的内容创建面向公众的视图。 错误使用模型可能会导致尴尬的副作用,例如页面无法更新其内容或应用程序占用大量内存。 从我所看到的,新的Wicket用户遇到的大多数问题是正确使用模型。 在这篇博客文章中,我将尝试解释在不同的用例中应如何以及应使用哪种模型。

Wicket IModel实现中最基本的是Model类。 它基本上是模型内容的简单占位符。 这非常适合模型内容不占用太多内存并且更像是常量的情况。 一个简单的String可能是Model内容的理想选择。

IModel<String> name = new Model<String>("John");

您必须了解,即使创建包含模型的页面,创建模型对象时其内容也将保持不变。 此行为是由于使用静态模型引起的。 每次从模型询问值时,动态模型都可以更改实际内容。 新的Wicket用户经常使用静态模型而不是动态模型。 如果您不清楚静态模型和动态模型的概念,则应阅读《 Wicket in Action 》一书中的第4章“了解模型” 。

IModel<Date> date = new Model<Date>() {@Overridepublic Date getObject() {return new Date();}
};

上面的动态日期模型是通过重写getObject()方法从Model创建为匿名类的。 模型将始终返回包含当前时间的Date的新副本。

Wicket是有状态的Web框架,模型通常存储在用户的HTTP会话中。 模型中的数据很可能是从数据库或通过某些Web服务获取的。 如果使用静态模型方法,我们将很快吞噬大量内存,并且如果重新加载页面,将无法从数据源获得全新的视图。 如果我们决定像对Date对象那样使用动态模型,则最终可能会在一页加载内进行大量数据库搜索或Web服务调用。 匿名内部类也不是很好看的代码。 Wicket有一个针对此问题的内置解决方案,LoadableDetachableModel可以缓存模型的内容,直到可以安全丢弃为止,从而提供了有效但仍动态的模型。

public class PersonModel extends LoadableDetachableModel<Person> {private Long id;private PersonService personService;public PersonModel(final Long id, final PersonService personService) {super();this.id = id;this.personService = personService;}public PersonModel(final Person person, final PersonService personService) {super(person);this.id = person.getId();this.personService = personService;}@Overrideprotected Person load() {return personService.findById(id);}
}

上面的示例构造了一个可加载和可拆卸的模型,用于通过其唯一标识符加载一个人。 该模型有两个构造函数,这是有原因的。 之一来创建在拆卸状态下的延迟加载模式,将加载内容当getObject()方法被调用第一次,和一个以在安装状态的模型,不需要到PersonService呼叫时的getObject()方法是叫。 最好为所有LoadableDetachableModels提供这两个构造函数。 您可以在已拥有内容的情况下以附加状态创建模型,或者在只有标识符可用时以分离状态创建模型。

可装载可分离模型的警告是模型的私有字段。 Wicket将模型和组件一起存储在页面存储中,这可能需要对模型进行序列化。 当模型被序列化时,私有字段也被序列化(实际内容被分离)。 我们的id字段不是问题,因为它可以序列化,但是PersonService可能是问题。 通常,服务层的接口默认情况下是不可序列化的。 至少有两种不错的解决方案:使服务可序列化,或者更好的方法是将服务包装在可序列化的代理中。 代理行为可以例如通过与不同的依赖项注入框架(例如)集成来实现。 春天(wicker-spring)或Guice(wicket-guice)。 集成模块可确保在注入服务代理时将它们可序列化。

public class ProfilePage extends WebPage {@SpringBeanprivate PersonService personService;public ProfilePage(final PageParameters parameters) {super(parameters);Long id = parameters.get("id").toLongObject();IModel<Person> personModel =new PersonModel(id, personService);add(new ProfilePanel("profilePanel", personModel));}
}

上面的示例使用wicket-spring集成将人员服务注入到所需页面。 @SpringBean批注提供了一个可序列化的代理,因此,当我们创建人员模型时,我们不必担心服务的序列化。 Wicket不允许构造函数注入,因为当我们调用super()构造函数时,所有注入魔术实际上都会发生。 这意味着我们在Component的基本构造函数完成之后初始化注入的值。 只需记住对数据使用可序列化的标识符或定位符,对服务使用可序列化的代理。

通常,在MVC Web框架中,视图层使用某种数据传输对象来构建视图。 DTO组成并继承以创建不同类型的视图。 为这些对象建立工厂或映射器可能容易出错或令人沮丧。 Wicket针对此问题提供了不同的解决方案。 在Wicket中,您可以认为IModel接口的工作方式类似于关系数据库视图,该视图允许您以不同的方式显示域的所需部分。

public class PersonFriendsModel extends AbstractReadOnlyModel<String> {private IModel<Person> personModel;public PersonFriendsModel(final IModel<Person> personModel) {super();this.personModel = personModel;}@Overridepublic String getObject() {Person person = personModel.getObject();Iterable<String> friendNames =Iterables.transform(person.getFriends(),new PersonNameFunction());return person.getName()+ "'s friends are "+ Joiner.on(", ").join(friendNames);}@Overridepublic void detach() {personModel.detach();}private class PersonNameFunction implements Function<Person, String> {public String apply(final Person input) {return input.getName();}}
}

在这里,我们构建了一个模型,该模型可以构成我们先前创建的PersonModel。 我们将其用作来源,以建立该人的好友列表。 我们正在扩展的模型是Wicket提供给我们的AbstractReadOnlyModel。 它基本上是普通模型,但不允许设置模型内容。 这非常有道理,因为我们正在构建一个连接的String,并且解析一个相似的列表并从该列表中设置该人的朋友会很尴尬。 我们仅将此模型用于只读目的,以在视图中显示朋友列表。 您可以在此处看到类似的视图,我们仍在使用相同的Person域模型,但是在模型的帮助下从中公开了一个自定义视图。 请注意,我们将detach方法委托给了组合模型。 这可以确保,如果我们在任何组件中都没有直接引用组成的模型,则仍然可以将其与好友模型分离。 多次调用detach()方法无害,因此即使从多个组件中使用也很安全。

我们仅创建了一个简单的模型合成示例。 您应该探索Wicket的内置模型实现,并花一些时间来研究如何使用域模型来创建合理的模型。 只需记住一件事:组成和扩展模型,而不是域对象。

我最后要谈的是属性模型。 它们在许多Wicket应用程序中得到了广泛使用,甚至《 Wicket in Action》一书也鼓励使用它们,但是它们具有一些不需要的功能。 属性模型的代码编写速度快且易于使用,但是它们使您的代码成为“字符串类型”。 这是我们不希望使用Java这样的类型安全语言的东西。

PropertyModel<String> nameModel =new PropertyModel<String>(personModel, "name");

我们使用PropertyModel从人的名字创建一个模型。 名称模型可以使用直接的Person对象或为我们提供人物的IModel。 可以通过实现Wicket的IChainingModel接口来实现此功能。 我们这里有两个问题。 第一个是名称模型的类型。 我们定义名称必须为String,但实际上编译器无法确保该名称已绑定到String getName() JavaBean属性。 第二个问题来自重构,我们使用String值定义属性名称。 如果使用IDE重构Person对象,并将getName()方法挂接getLastName() ,则应用程序将损坏 ,编译器将再次无法注意到这一点。

让我们在这里停留片刻,看看IChainingModel接口。 其主要目的是允许使用普通对象或链接模型作为模型的内容。 PropertyModel可以与提供人物的模型或普通人物对象一起使用。 如果查看PropertyModel的源代码,则会注意到实现IChainingModel需要转换,而我认为还需要样板代码。 可以重构我们先前创建的PersonFriendsModel,以实现IChainingModel,这样,与其仅采用模型作为内容,它还可以支持直接采用人员。这真的有必要吗? 并不是的。 如果我们要使用普通人,则可以从该人创建一个新的静态模型,从而为我们提供与IChainingModel相同的功能。

CompoundPropertyModel为模型处理增加了更多的魔力。 它是许多组件的根模型,可以通过将属性名称与组件ID匹配来自动绑定到该组件。

public class PersonForm extends Form<Person> {public PersonForm(final String id, final IModel<Person> personModel) {super(id, new CompoundPropertyModel<Person>(personModel));add(new TextField<String>("name"));add(new TextField<Integer>("age"));}
}

在这里,我们创建一个表单以显示该人的姓名和年龄的输入字段。 这两个文本字段均未附加任何模型,但是我们仍然能够将“名称”部分绑定到该人的姓名,并将“年龄”部分绑定到该人的年龄。 我们在构造函数中创建的复合属性模型是表单的根模型,并通过组件ID将表单组件自动绑定到对象的属性。 复合属性模型和属性模型都存在相同的问题,但我们甚至还要添加一个。 现在,我们将组件ID直接锁定为属性名称。 这意味着我们具有从HTML模板到域对象属性名称的依赖关系。 这听起来不太合理。

如果要使用属性模型,则取决于您,但是在我看来,由于前面所述的问题,应避免使用它们。 有诸如bindgen-wicket之类的项目尝试在不损失类型安全性的情况下实现属性模型的行为。 但是,即使bindgen在重构中也无法很好地起作用。 我们如何以一种类型实现名称模型并以安全的方式重构呢?

public class NameModel implements IModel<String> {private IModel<Person> personModel;public NameModel(final IModel<Person> personModel) {this.personModel = personModel;}@Overridepublic String getObject() {return personModel.getObject().getName();}@Overridepublic void setObject(String object) {personModel.getObject().setName(object);}@Overridepublic void detach() {personModel.detach();}
}

该模型比属性模型具有更多的行。 是的,的确如此,但是您是否想失去类型安全性和重构功能,并可能很容易破坏应用程序。 该模型位于不同的文件中,因此您仍然可以将其用作一个衬纸,因此,如果使用属性模型或我们刚刚创建的模型,则没有任何区别。 您永远可以记住Java是非常冗长的语言这一事实​​。

Wicket还为我们提供了ResourceModel和StringResourceModel,它们提供了为组件创建本地化内容的强大工具。 我不会在本文中讨论它们,因为《 Wicket in Action》一书对此有很好的参考。 我试图提出一些现实生活中的示例,说明如何使用不同类型的模型以及它们的目的是什么。 我希望这能给您更多有关Wicket模型以及如何正确使用它们的知识。

参考:来自RAINBOW WORLDS博客的JCG合作伙伴 Tapio Rautonen 对Wicket模型的一种干净方法 。

翻译自: https://www.javacodegeeks.com/2013/09/a-clean-approach-to-wicket-models.html

wicket

wicket_Wicket模型的干净方法相关推荐

  1. Wicket模型的干净方法

    Apache Wicket Web框架的核心概念之一是模型和IModel作为其编程接口. Wicket组件严重依赖模型,这使它们成为体系结构的重要组成部分. Apache Wicket是一个有状态框架 ...

  2. thinkphp模型中的获取器和修改器(根据字段名自动调用模型中的方法)

    thinkphp模型中的获取器和修改器(根据字段名自动调用模型中的方法) 一.总结 记得看下面 1.获取器的作用是在获取数据的字段值后自动进行处理 2.修改器的作用是可以在数据赋值的时候自动进行转换处 ...

  3. python caffe 训练自己的模型_python接口调用已训练好的caffe模型测试分类方法

    训练好了model后,可以通过python调用caffe的模型,然后进行模型测试的输出. 本次测试主要依靠的模型是在caffe模型里面自带训练好的结构参数:~/caffe/models/bvlc_re ...

  4. IOS应用管理学习,进阶,涉及字典转模型,工厂方法,面向对象思想,页面布局等

    IOS应用管理学习,进阶,涉及字典转模型,工厂方法,面向对象思想,页面布局等 前言:人为规定的参数 每一个 小view视图 宽度 80 高度 90 数据类型 CGFloat 定义, 3 列,数据类型 ...

  5. python保存模型与参数_基于pytorch的保存和加载模型参数的方法

    当我们花费大量的精力训练完网络,下次预测数据时不想再(有时也不必再)训练一次时,这时候torch.save(),torch.load()就要登场了. 保存和加载模型参数有两种方式: 方式一: torc ...

  6. 模型保存的方法-----仅保存权重

    模型保存的方法-----仅保存权重 1.意义 有时我们只需要保存模型的状态(其权重值),而对模型架构不感兴趣.这种情况下,可以通过get_weights()获取权重值,并且通过set_weights( ...

  7. 模型保存的方法-----仅保存架构

    模型保存的方法-----仅保存架构 1.意义 如果只对模型的架构感兴趣,则无需保存权重值或优化器.这种情况下,可以只保存模型的配置. 2.分析过程 #获得模型的架构 json_config=model ...

  8. 模型保存的方法-----保存整个模型

    模型保存的方法-----保存整个模型 1.先训练一个模型

  9. 性能翻倍!斯坦福Matei团队推出机器学习模型优化新方法

    机器学习模型正在被越来越多地部署在任务关键型系统中,比如自动驾驶汽车.然而,这些模型可能会因为各种复杂的原因失效,应用程序开发人员必须找到调试这些模型的方法.我们建议在ML模型调试任务中使用软件断言. ...

最新文章

  1. centos6.7 安装redis
  2. final阶段团队贡献分分配
  3. ABAP设置输入焦点和表格控件行数的注意事项
  4. flink source 同步_为什么说 Flink + AI 值得期待?
  5. mysql 的驱动是多少_mysql驱动参数变化
  6. OpecCV颜色分割
  7. MySQL错误:The user specified as a definer (XXX@XXX) does not exist (1449错误)最简解决方案...
  8. python 长时间运行 会停止_如何“停止”和“恢复”长时间运行Python脚本?
  9. 所有的低谷,都是为了更上一层楼
  10. SICP习题解答2.22
  11. dataframe 如何选中某列的一行_Spark中的RDD、DataFrame和DataSet讲解
  12. python写的代码怎么发给别人_用python 代码 怎么给别人发邮件的两种写法
  13. SQL中使用正则表达式
  14. 3月6日服务器例行维护公告,热血江湖官方网站·系统公告
  15. 【Python】绘制三维立体图
  16. 华为初面+综合面试(技术面)
  17. SA6155P max9288 camera 笔记-2
  18. 事关健康、教育和工资 | 1月起,这些事有变化 |
  19. UiPath:Windows计划任务调度UiPath(直接调用及.bat方式)
  20. 达梦数据库和mysql索引引擎_达梦数据库如何建索引和使用

热门文章

  1. K8S Learning(7)—— Deployment
  2. Spring MVC 到底是如何工作的
  3. 这些Spring面试题,你都会了吗?
  4. 阿里巴巴对Java编程【OOP规约】的规约
  5. 吃透这套架构演化图,从零搭建Web网站也不难
  6. Vue及React脚手架安装
  7. 【Python】有效资源爬取并集
  8. 【最全最详细】使用publiccms实现动态可维护的首页轮播
  9. 第二章 变量、数据类型和运算符
  10. Ajax判断用户名是否可用