一步一步来。
在进行下一步之前,一切都必须按预期进行,这一点很重要。
继续使用JSTL动态构建视图
只需继续使用JSTL,并仅替换JSP包含项,
<ui:include>直到一切正常即可。不要改变太多。首先使其全部正常工作,然后将其重构为标记文件或复合文件。
在最初的JSP方法中,您基本上是在JSTL的帮助下动态构建视图。您可以继续在JSF 2.x中执行相同的操作,前提是您使用的是最新的JSF
impl版本,以防止损坏视图作用域的bean(Mojarra
2.1.18+)。您可以继续使用
<c:forEach>,
<c:if>而
<c:set>这样的JSF。您只需要更换
@include和
<jsp:include>通过
<ui:include>。请注意,它
<ui:include>具有与JSTL相同的生命周期。它也是标记处理程序,而不是组件。另请参见JSF2
Facelets中的JSTL …有意义吗?
的
<ui:fragment>,但是,是一个UI组件。它不会有条件地构建视图。无论其
rendered属性的结果如何,它及其所有子代仍将最终出现在JSF组件树中。他们只会在渲染响应阶段有条件地渲染HTML输出。与之相比的收益
<c:if>是,对于每种条件,JSF组件树的大小都会增加。假设您在该
inc_dynamic_checklist_v文件中有4个条件包含,那么它的大小至少会增长4倍。只需继续使用JSTL即可动态构建视图。这是一个非常好的工具。另请参见ao
如何制作JSF复合组件的网格?另一种方法是通过手动创建在背衬bean组件
binding,
findComponent(),
createComponent(),
newSomeComponent(),
getChildren().add()否则,这只会导致冗长而脆弱的代码,而这些代码很难维护。绝对不要那样做。
在
<f|o:viewParam>你失败的尝试如用于不同的用途。正如您所期望的那样,它们无法对中的
<ui:param>值采取行动
<ui:include>。它们仅对HTTP请求参数起作用。另请参见
<ui:include>继续使用
<ui:param>来代替
<c:set>,但是您应该像直接使用一样直接访问它们
<c:set>。唯一的区别是,这些变量仅在包含本身内部可用,而不是在整个请求中可用(即,因此也可以在包含外部使用)。
<ui:param>顺便说一句
<jsp:param>,您实际上应该首先使用JSP的等效项。
对于支持bean逻辑,只需将支持Java的预处理Java代码放入
@PostConstruct支持bean
中,将支持Java的后处理Java代码放入与
<h:commandXxx>组件绑定的支持bean的操作方法中即可。在
<f:viewAction>和
preRenderView因为他们认为建造时间后跑多远,因此JSTL不会得到它期望的模型是insuitable。仅使用这些参数来处理用户提交的HTTP请求参数。
如果您在较旧的Mojarra版本中被Chicken-
egg视图状态错误所咬伤,并且您绝对不能升级,也不能通过将设置
javax.faces.PARTIAL_STATE_SAVING为来禁用部分状态保存
false,那么您就不能将JSTL标记属性附加到查看作用域的bean中属性。如果您确实在这里有一个范围内的视图bean,并且不是在这里使用请求范围内的bean的选项,则需要删除JSTL并专门使用
<ui:repeat>and
<ui:fragment>代替
<c:forEach>and
<c:if>。但是,您可以继续使用
<c:set>(如果适用)。您还应该保留上述支持bean逻辑的准则。
将重复的包含参数重构为标记文件
一旦一切
<ui:include><ui:param>就绪,您就可以开始查看重复的包含参数(即,多次使用的块),并通过简单地将它们注册到
your.taglib.xml文件中将它们重构为标记文件。实际上,这不会改变逻辑和流程,但会使代码更简洁明了。另请参阅如何创建自定义Facelets标签?有关完整的
*.taglib.xml示例和在中的注册
web.xml。
这个虚构的示例包括“是/否/不适用检查表”
<ui:include src="/WEB-INF/includes/tristateChecklist.xhtml"> <ui:param name="value" value="#{actionItem}" /></ui:include>…可以如下使用
<my:tristateChecklist value="#{actionItem}" />…将物理文件移入
/WEB-INF/tags/tristateChecklist.xhtml并按
/WEB-INF/your.taglib.xml如下所示进行注册后,所有包含参数均作为标记属性。
<tag> <tag-name>tristateChecklist</tag-name> <source>tags/tristateChecklist.xhtml</source> <attribute> <name>value</name> <type>java.lang.Object</type><!-- TODO: fix type --> </attribute></tag>
(您没有显示您的模型,所以我只指定了一个过于泛型的类型)
将重复的模型预处理/后处理重构为复合材料
一旦一切恢复正常,您就可以开始研究重复的模型预处理/后处理,并将它们重构为带有“后备组件”以及内部关联的XHTML的复合文件
<cc:implementation>。
基本上,当您有很多Java代码
@PostConstruct可以将服务/数据库返回的“外部”模型转换为视图所期望的“内部”模型时,和/或当您有很多Java代码在使用方法时按照服务/数据库的期望将“内部”模型转换回“外部”模型,那么您可以考虑将其重构为可重用的复合组件。这样,当您想在不同的视图中重用相同的功能时,就无需将该粘贴/重复此预处理/后处理任务复制/粘贴到其他支持bean中。并且,您最终得到一个视图,该视图精确地引用了“外部”模型类型而不是“内部”模型类型,该模型类型可能包含多个属性。
如果没有全面了解所有模型的前/后处理,则很难用特定案例的示例来回答这一部分。以下答案包含一些示例,这些示例应该可以对复合组件的意义和废话提供足够的了解:
- 用f:convertDateTime在两个表示小时和分钟的h:inputText字段上拆分java.util.Date
- 根据提供的属性初始化复合组件
- 升级到JSF 2.2后,#{cc.clientId}在错误的组合中评估
至少,我的印象是您的“肉”可能是一个界面。如果您具有相同行为的不同对象/类,则应创建一个定义该行为的接口,并让这些类实现该接口。反过来,这部分与JSF并不严格相关,而只是“基本”
Java。
别忘了:一次一步。
使用标记文件和组合作为重构工具,以最大程度地减少代码重复。您应该已经有完整的工作代码。



