You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:00:03