我正在尝试在XPage项目中实现适当的层分离。理想情况下,我试图使XPage中的XML不包含SSJS并仅使用EL来访问Java对象。
到目前为止,我已经研究出如何将所有数据从多米诺骨牌数据库加载到Java Beans(其中1个文档= 1个对象,或多或少),我正在将视图内容读入Java Maps或Lists中,在重复控件中显示这些集合的内容。
我不确定的是如何在不引用多米诺骨牌文档的情况下显示单个文档的“表单”的内容。特别是,我不确定如何处理“新文档”案。我想我创建一个空对象,然后将该对象设置为Xpage的数据源。
我知道我必须为此使用ObjectDataSource,但是我不确定在哪里实际存储它。我读了Stephan Wissel的一篇文章,指出不应将它们放入托管bean中,那我可以放在哪里?在像viewScope这样的作用域变量中?
现在,我编写了一个“ ApplicationBean”,它是一个会话范围的托管Bean,用于存储所有对象。
最佳实践是什么?似乎有许多不同的方法可以实现该目标。目前,我正在探索ChristianGüdemann的XPages Toolkit,这听起来很有希望。我知道Samir Pipalia,John Daalsgard和Frank van der Linden已经制定了自己的框架。
那我该怎么办呢?有什么陷阱吗?
这确实是一个大话题。正如Paul所提到的,Tim的文档模型类是如何清楚地做到这一点的一个很好的例子,Tim在该NotesIn9系列的后续文章中对此进行了更详细的介绍。我自己的Framework的模型对象相当相似,尽管我还添加了集合管理器来处理访问视图的肮脏事务。不管是好是坏,几乎每个XPage开发人员都以独特的方式解决了这个问题。
您可以通过多种方式来实现这种事情,并且在正常情况下,其中一些差异并不是非常重要(例如,在构造模型对象时是从文档中预加载所有数据还是进行懒惰提取)到后端(仅在需要时)),但是肯定要解决几个总体问题。
正如您在问题中提到的,最大的问题之一是您实际上如何从XPage访问模型对象-如何从数据库中获取对象或如何重新创建对象。My Framework的模型对象使用“ Manager”对象的概貌,这些对象是应用程序范围的Bean,它们允许获取命名集合(映射到视图),通过UNID获得模型对象,或通过关键字“ new”获得新的模型对象。一般情况下,这些模型(这是序列化),或者通过使用它们,然后存储在页面视图范围<xp:dataContext/>,<xe:objectData/>或框架本身<ff:modelObjectData/>。
我发现避免使用托管bean来表示单个对象(例如“ CurrentWhatever”,然后在每个页面上填充数据)是非常明智的,因为在最佳情况下这会使您的faces-config变得混乱,或者遇到会话问题。最坏的情况(如果您将其放在会话范围中,我很少使用)。
如何实现“新”与“获取”模型对象的方式很大程度上取决于首先要编写模型的方式,但是大多数归结为拥有两个构造函数:一个构造函数(至少要带一个UNID)指向现有文档,然后创建一个新文档。如果使用“使用getter和setter显式地在对象中正确编写每个对象”路由,则后者还将使用默认值初始化所有字段,而不是从文档中读取它们。在内部,您应该具有用于存储文档UNID的字段,该字段可以指示它是否是新的-然后,您的save方法可以检查该字段是否为空,并在需要时创建一个新文档(然后存储新文档的UNID在该领域)。
听起来您已经将模型集合读入Lists中,这很好。但是,缺点是可伸缩性:较小的集合(少于100个),您可能不会遇到任何加载速度问题,但是之后,随着代码的读入,事情将减慢初始页面加载的速度提前查看整个视图。您可以通过有效的视图阅读来缓解这种情况,但这是有限制的。内置视图通常速度很快,因为它们仅根据需要加载数据(它们也像地狱一样作弊,但这是另一个问题)。
这是针对自己的一个崇高目标,但这样做可以覆盖所有情况并非易事:您最终遇到了FT搜索,列重新排序,有效的数据预加载等问题(您不想重新打开View对象只能一次读入一个条目,但是您也不想读完整的东西),用于viewPanel其他对象(需要专门的接口),扩展/折叠类别等等。它本身就是一个很大的子主题。
您还可能会遇到比起初想像的还要困难的其他区域,例如“适当的”富文本格式处理和文件附件。附件尤其需要与XSP框架直接冲突,才能与自定义模型对象和标准上载/下载控件一起正常运行。
字段名称中的区分大小写是另一个潜在的麻烦领域。如果您要为所有字段编写getter和setter方法,那么这是有争议的,但是,如果要采用“薄包装”路线(我更喜欢),那么对任何中间缓存/查找进行编码就很重要,处理以下事实:“ FOO”和“ foo”(基本上)与Notes的项目名称相同,但在Java中是不同的。我的主旨是充分利用TreeMaps:如果String.CASE_INSENSITIVE_ORDER将参数作为参数传递给构造函数,则在将String用作键时,通常会将其视为不区分大小写。
让您的模型对象与诸如此类的所有标准控件一起工作可能不是优先事项-我发现它非常有价值,因此我做了很多工作来使其在我的框架中实现,但是如果您要做的话一些基本的字符串和数字模型,您不必担心。
所以...是的,这是个大话题!根据您对Java和XPages基本知识的信心程度,我建议您为对象选择较为简单的“带有getter和setter的bean”路线,或者通过研究现有框架之一(我自己的框架)的实现细节或您提到的内容)。可悲的是,随着代码变得越来越复杂,会有很多小事情涌现出来,其中许多事情并不是显而易见的。