jef*_*eff 7 jsf jsp facelets composite-component
ORIGINAL JSP(WorkItem.jsp)
<c:forEach var="actionItem" items="${workItem.work_action_list}">
<c:if test="${actionItem.workActionClass.work_action_type_id == '1'}" >
<%@ include file="inc_done_button.jsp" %>
</c:if>
<c:if test="${actionItem.workActionClass.work_action_type_id == '2'}" >
<c:set var="actionItem" value="${actionItem}" scope="request" />
<c:set var="checklist" value="${actionItem.meat}" scope="request" />
<jsp:include page="inc_dynamic_checklist_v.jsp" flush="true" />
</c:if>
etc...
</c:forEach>
Run Code Online (Sandbox Code Playgroud)
原始Java
for (ListIterator<WorkflowInstanceWorkItemAction> actionIter = wfiwi.getWork_action_list().listIterator(); actionIter.hasNext();) {
if ("2".equals(work_action_type_id)) {
ChecklistInstanceForm ciForm = new ChecklistInstanceForm(this, authenticatedUser);
ChecklistInstance ci = null;
ci = (ChecklistInstance) ciForm.getChkLstInstanceByWfiWiaOwner(wfiWorkItemAction, authenticatedUser);
// Get the meat details for this action and inject it into the object
wfiWorkItemAction.setMeat(ci);
}
}
request.setAttribute("workItem", wfiwi);
request.setAttribute("workFlowInstance", wfi);
Run Code Online (Sandbox Code Playgroud)
新JSF(WorkItem.xhtml)
<f:metadata>
<o:viewParam name="wfi_wid" value="#{workItemController.wfiwi}" converter="#{workItemConverter}"
<f:event type="preRenderView" listener="#{workItemController.preRender}" />
</f:metadata>
<ui:repeat var="actionItem" value="#{workItemController.wfiwi.work_action_list}">
<ui:fragment rendered="#{actionItem.workActionClass.workActionType.action_type_id == '1'}">
<stk:done_button actionItem="#{actionItem}" /> <!-- Here I chose custom c -->
</ui:fragment>
<ui:fragment rendered="#{actionItem.workActionClass.workActionType.action_type_id == '2'}">
<ui:include src="inc_dynamic_checklist.xhtml">
<ui:param name="checklist" value="#{actionItem.meat}" />
</ui:include>
</ui:fragment>
Run Code Online (Sandbox Code Playgroud)
我的新支持豆的料
public class WorkItemController implements Serializable {
private static final long serialVersionUID = 1L;
private WorkflowInstanceWorkItem wfiwi;
public void preRender() {
if (wfiwi.getWork_action_list() != null) {
//loop through and add real model to meat attribute
Run Code Online (Sandbox Code Playgroud)
我所追求的是一种更优雅的方式将模型(我称之为肉)注入每个动作的视图中.在工作项(单页面视图)下,有多个操作.作为清单的动作可以是各种类型(是/否/ na,数量主要/次要,是/否/ na /已解决等).
复合组件done_button
是直截了当的,因为我只访问基本action
模型而没有meat
.例如,done_button.xhtml
复合组件的片段
<ui:fragment rendered="#{cc.attrs.actionItem.is_active != '1'}">
Action is not active for you until the following has been completed:
<h:outputText value="#{cc.attrs.actionItem.prerequisite_work_action_list}" escapeXml="false" />
</ui:fragment>
Run Code Online (Sandbox Code Playgroud)
但是dynamic_checklist facelet代码的包含让我感到困惑,因为我将各种注入Objects
到这个通用属性中的方法meat
似乎是错误的.在我使用<c:set var="checklist" value="${actionItem.meat}" scope="request" />
的原始JSP中,然后原始的JSP inc_dynamic_checklist_v.jsp
看起来像
inc_dynamic_checklist_v.jsp
<form method="post" >
<c:out value="${actionItem.workActionClass.name}" />
<c:if test="${checklist.checkListClass.type == '1'}" >
<%@ include file="inc_yes_no_na_resolved_checklist.jsp" %>
</c:if>
<c:if test="${checklist.checkListClass.type == '2'}" >
<%@ include file="inc_major_minor_checklist.jsp" %>
</c:if>
<c:if test="${checklist.checkListClass.type == '3'}" >
<%@ include file="inc_quantity_checklist.jsp" %>
</c:if>
<c:if test="${checklist.checkListClass.type == '4'}" >
<%@ include file="inc_yes_no_na_checklist.jsp" %>
</c:if>
Run Code Online (Sandbox Code Playgroud)
那些包括还需要访问actionItem.meat,它是在WorkItem.jsp中使用c:set设置的
我正在寻找指导,是的,我应该将所有这些包括转换为复合组件,即使我有嵌套包含.或者我应该使用基本的ui:includes?我知道我可以param
使用include或cc 发送但是我仍然private Object meat
在我的模型中使用通用字段,或者是否有更好的方法来检索这些单独的动作模型.
或许这样但它没有用
<ui:include src="inc_dynamic_checklist.xhtml" >
<ui:param name="wfi_id" value="#{actionItem.workflowInstance.workflow_instance_id}" />
<ui:param name="wfi_aid" value="#{actionItem.wfi_work_item_action_id}" />
</ui:include>
Run Code Online (Sandbox Code Playgroud)
然后在inc_dynamic_checklist.xhtml中
<f:metadata>
<o:viewParam name="wfi_id" value="#{checklistInstanceView.ci}" converter="#{checklistInstanceConverter}">
<f:attribute name="wfi_id" value="#{param.wfi_id}" />
<f:attribute name="wfi_aid" value="#{param.wfi_aid}" />
</o:viewParam>
</f:metadata>
Run Code Online (Sandbox Code Playgroud)
UPDATE
工作项支持bean.工作项包含一系列操作.可以执行操作按钮(操作类型id = 1)清单(操作类型id = 2),以及未实现/显示的其他内容.我现在有什么用,但这是正确的方法吗?
public void preRender() {
if (wfiwi.getWork_action_list() != null) {
for (ListIterator<WorkflowInstanceWorkItemAction> actionIter = wfiwi.getWork_action_list().listIterator(); actionIter.hasNext();) {
WorkflowInstanceWorkItemAction wfiWorkItemAction = new WorkflowInstanceWorkItemAction();
wfiWorkItemAction = actionIter.next();
Long work_action_type_id = wfiWorkItemAction.getWorkActionClass().getWorkActionType().getAction_type_id();
updatePrerequisites(wfiWorkItemAction, wfiwi.getWorkflowInstance(), wfiwi);
if (work_action_type_id == 2) {
System.out.println("Action Type 2 is Dynamic Checklist Type");
ci = ciRepository.retrieveLatestByWfiWiai(wfiwi.getWorkflowInstance().getWorkflow_instance_id(), wfiWorkItemAction.getWfi_work_item_action_id());
if (ci != null) {
if ("1".equals(ci.getCheckListClass().getType())) {
List<YesNoNaResolvedAnswer> answer_attribute_list = yesNoNaResolvedDao.retrieveByCiWfi(ci.getChecklist_instance_id(), ci.getWorkflowInstance().getWorkflow_instance_id());
ci.setAnswer_attribute_list(answer_attribute_list);
}
if ("2".equals(ci.getCheckListClass().getType())) {
List<MajorMinorAnswer> answer_attribute_list = majorMinorAnsDao.retrieveByCiWfi(ci.getChecklist_instance_id(), ci.getWorkflowInstance().getWorkflow_instance_id());
ci.setAnswer_attribute_list(answer_attribute_list);
}
if ("3".equals(ci.getCheckListClass().getType())) {
List<QuantityAnswer> answer_attribute_list = quantityAnsDao.retrieveByCiWfi(ci.getChecklist_instance_id(), ci.getWorkflowInstance().getWorkflow_instance_id());
ci.setAnswer_attribute_list(answer_attribute_list);
}
if ("4".equals(ci.getCheckListClass().getType())) {
List<YesNoNaAnswer> answer_attribute_list = yesNoNaAnsDao.retrieveByCiWfi(ci.getChecklist_instance_id(), ci.getWorkflowInstance().getWorkflow_instance_id());
ci.setAnswer_attribute_list(answer_attribute_list);
}
wfiWorkItemAction.setMeat(ci);
} else {
Messages.addFlashErrorMessage("Could not find checklist Instance");
}
// wfi_action_list.add(ci);
} else {
wfiWorkItemAction.setMeat("meat pie");
}
}
}
Run Code Online (Sandbox Code Playgroud)
}
inc_dynamic_checklist.xhtml(请参阅上面的WorkItem.xhtm以了解如何包含它)这显示"肉"
<ui:fragment rendered="#{checklist.checkListClass.type == '1'}">
<ui:include src="inc_yes_no_na_resolved_checklist.xhtml" />
</ui:fragment>
<ui:fragment rendered="#{checklist.checkListClass.type == '2'}">
<ui:include src="inc_major_minor_checklist.xhtml" />
</ui:fragment>
<ui:fragment rendered="${checklist.checkListClass.type == '3'}">
<ui:include src="inc_quantity_checklist.xhtml" />
</ui:fragment>
<ui:fragment rendered="${checklist.checkListClass.type == '4'}">
<ui:include src="inc_yes_no_na_checklist.xhtml" />
</ui:fragment>
Run Code Online (Sandbox Code Playgroud)
模型
@Entity
public class WorkflowInstanceWorkItemAction implements Serializable {
private static final long serialVersionUID = 1L;
private String status;
private String is_active;
@Transient
private Object meat;
and various mappings
Run Code Online (Sandbox Code Playgroud)
一步一步来.
重要的是,在进入下一步之前,一切都按照预期的方式继续工作.
只需继续使用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()
,new SomeComponent()
,getChildren().add()
什么不是,这只会导致难以维护的冗长而脆弱的代码.绝对不要那样做.
在<f|o:viewParam>
你失败的尝试如用于不同的用途.正如你所期望的那样,他们无法对<ui:param>
价值观念采取行动<ui:include>
.它们仅对HTTP请求参数起作用.另请参见<f:metadata>,<f:viewParam>和<f:viewAction>可以用于什么?您可以<ui:include>
继续使用<ui:param>
而不是<c:set>
,但您应该直接访问它们,就像您一样<c:set>
.唯一的区别是这些变量仅在包含本身内部而不是在整个请求中可用(即因此也在包含之外).<ui:param>
顺便说一下JSP的等价物<jsp:param>
,你实际上应该首先使用它.
至于支持bean逻辑,只需将预处理Java代码放在@PostConstruct
支持bean中,并将后处理Java代码放在支持bean的操作方法中,绑定到<h:commandXxx>
组件.在<f:viewAction>
和preRenderView
因为他们认为建造时间后跑多远,因此JSTL不会得到它期望的模型是insuitable.仅用于处理用户提交的HTTP请求参数.
如果你用鸡-蛋视图状态错误在一个旧钻嘴鱼科的版本咬伤,你绝对不能升级,也可以通过设置禁用部分状态保存javax.faces.PARTIAL_STATE_SAVING
到false
,那么你可以不重视JSTL标签属性查看作用域bean属性.如果你在这里确实是一个视图范围的bean,而且这里不能使用请求范围的bean,你需要删除JSTL并专门使用<ui:repeat>
而<ui:fragment>
不是<c:forEach>
和<c:if>
.但是,您可以继续使用<c:set>
(如果适用).您还应该遵循上面描述的支持bean逻辑的准则.
一旦你完成所有工作,那么你可以开始查看重复的include-with-params(即<ui:include><ui:param>
不止一次使用的块),并通过简单地将它们注册到your.taglib.xml
文件中来重构它们到tagfiles .这实际上并没有改变逻辑和流程,但使代码更加干净和简洁.另请参见如何创建自定义Facelets标记?完整的*.taglib.xml
例子和注册web.xml
.
这个虚构的例子包括"是/否/ na清单"
<ui:include src="/WEB-INF/includes/tristateChecklist.xhtml">
<ui:param name="value" value="#{actionItem}" />
</ui:include>
Run Code Online (Sandbox Code Playgroud)
......可以如下使用
<my:tristateChecklist value="#{actionItem}" />
Run Code Online (Sandbox Code Playgroud)
...将物理文件移入/WEB-INF/tags/tristateChecklist.xhtml
并注册后,将/WEB-INF/your.taglib.xml
所有include参数作为标记属性.
<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>
Run Code Online (Sandbox Code Playgroud)
(你没有展示你的模型,所以我只指定了一个过于通用的类型)
一旦你再次完成所有工作,那么你可以开始查看重复的模型前/后处理,并将它们重构为具有"后备组件"的复合材料,以及内部相关的XHTML <cc:implementation>
.
基本上,当您有相当多的Java代码@PostConstruct
将服务/ DB返回的"外部"模型转换为视图所期望的"内部"模型时,和/或当您在操作方法中有相当多的Java代码时要将"内部"模型转换回服务/ DB期望的"外部"模型,那么您可以考虑将其重构为可重用的复合组件.这样,当您想要在不同视图中重用相同的功能时,您不需要将此前/后处理任务复制/重复到不同的支持bean中.并且,您最终会得到一个视图,该视图完全引用"外部"模型类型而不是"内部"模型类型,可能包含多个属性.
如果您没有全面了解所有模型的前/后处理,那么这个部分很难用您的具体案例作为示例.以下答案包含的示例应该能够充分了解复合组件的含义和无意义:
至少,我的印象是你的"肉"可能是一个界面.如果您有不同的具有相同公共行为的对象/类,那么您应该创建一个定义该公共行为的接口,并让这些类实现该接口.这部分反过来并不是严格的JSF相关,而只是"基本的"Java.
别忘了:一次一步.
使用标记文件和合成作为重构工具来最小化代码重复.您应该已经拥有完整的代码.
归档时间: |
|
查看次数: |
1177 次 |
最近记录: |