JSF复合组件递归出现StackOverflowError问题求助
JSF递归复合组件踩坑:明明加了终止条件却爆StackOverflowError
之前我试着参考递归组件的实现思路,用JSF复合组件nested:cif做递归渲染,本来想着用<c:if>来写终止逻辑,理论上完全行得通,结果一运行直接炸了StackOverflowError,当时的代码片段大概是这样的:
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:cc="http://xmlns.jcp.org/jsf/composite" xmlns:nested="http://xmlns.jcp.org/jsf/composite/nested"> <!-- 这里是递归组件的具体逻辑,包含<c:if>终止条件 --> </html>
后来才搞明白问题出在哪——JSF的<c:if>是在视图构建阶段执行的,而不是我们以为的渲染阶段。也就是说,当JSF开始构建组件树的时候,它不会先去判断<c:if>的条件,而是一股脑地把所有递归调用的组件都往树里塞,直到栈被撑爆,根本轮不到终止条件生效。
那怎么解决呢?换用在渲染阶段生效的条件控制就行,比如用<h:panelGroup>的rendered属性代替<c:if>。因为rendered是在渲染页面的时候才会判断条件,组件树构建阶段只会创建一个复合组件实例,不会无限递归创建。
给你举个调整后的示例:
<!-- 复合组件nested:cif的内部代码 --> <!-- 先渲染当前节点内容 --> <h:outputText value="#{currentNode.label}" /> <!-- 用rendered控制是否递归渲染子节点 --> <h:panelGroup rendered="#{not empty currentNode.children}"> <nested:cif node="#{child}" /> </h:panelGroup>
这样改完之后,递归就会在渲染阶段根据节点是否有子节点来终止,不会再出现栈溢出的问题了。
内容的提问来源于stack exchange,提问作者Kalle Richter
相关产品推荐
相关产品推荐

