JSF与JSTL在XHTML页面中c:choose条件判断异常问题
JSF中<c:choose>条件判断不符合预期的排查与解决
问题现象
使用JSF开发XHTML页面时,发现<c:choose>标签内的<c:when>条件${pwaService.isTicketFromUser(tik.from) eq true},在后台方法实际返回false时,页面仍渲染right-msg区块,而非<c:otherwise>对应的left-msg区块。后台isTicketFromUser方法逻辑已验证可正常返回true或false,但页面表现不符合预期。
相关代码
页面头部标签
<?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:c="http://java.sun.com/jsp/jstl/core" xmlns:f="http://xmlns.jcp.org/jsf/core" xmlns:ui="http://xmlns.jcp.org/jsf/facelets" >
<c:choose>代码片段
<c:forEach items="#{pwaService.tickets}" var="tik"> <c:choose> <c:when test="${pwaService.isTicketFromUser(tik.from) eq true}"> <div class="msg right-msg"> <div class="msg-bubble"> <div class="msg-info"> <div class="msg-info-name">#{tik.from.name}</div> <div class="msg-info-time">#{pwaService.time(tik.sentDate)}</div> </div> <div class="msg-text"> #{tik.message} </div> </div> </div> </c:when> <c:otherwise> <div class="msg left-msg"> <div class="msg-bubble"> <div class="msg-info"> <div class="msg-info-name">مدیر سامانه</div> <div class="msg-info-time">#{pwaService.time(tik.sentDate)}</div> </div> <div class="msg-text"> #{tik.message} </div> </div> </div> </c:otherwise> </c:choose> </c:forEach>
后台Java方法
public boolean isTicketFromUser(User from) { return !from.getId().equals(UUID.fromString("hiddenUUID")); }
排查与解决思路
1. 简化EL布尔条件判断
EL表达式中,布尔类型的方法返回值无需额外与true做比较。原条件${pwaService.isTicketFromUser(tik.from) eq true}可以直接简化为${pwaService.isTicketFromUser(tik.from)}。
多余的eq true可能引发EL类型转换异常:若方法返回的Boolean包装类为null,EL会将其转换为false,但某些容器的转换逻辑可能出现偏差,导致判断结果不符合预期。简化后能避免这类潜在问题。
2. 替换JSTL标签为JSF原生组件适配生命周期
JSTL标签(<c:forEach>、<c:choose>)在视图构建阶段执行,而JSF的数据绑定逻辑在视图渲染阶段生效。如果pwaService.tickets的数据是在渲染阶段才完成加载,JSTL会提前基于未初始化的旧数据执行判断,导致页面渲染错误。
建议替换为JSF原生的<ui:repeat>和<h:panelGroup rendered>实现条件渲染:
<ui:repeat value="#{pwaService.tickets}" var="tik"> <h:panelGroup rendered="#{pwaService.isTicketFromUser(tik.from)}"> <div class="msg right-msg"> <div class="msg-bubble"> <div class="msg-info"> <div class="msg-info-name">#{tik.from.name}</div> <div class="msg-info-time">#{pwaService.time(tik.sentDate)}</div> </div> <div class="msg-text"> #{tik.message} </div> </div> </div> </h:panelGroup> <h:panelGroup rendered="#{!pwaService.isTicketFromUser(tik.from)}"> <div class="msg left-msg"> <div class="msg-bubble"> <div class="msg-info"> <div class="msg-info-name">مدیر سامانه</div> <div class="msg-info-time">#{pwaService.time(tik.sentDate)}</div> </div> <div class="msg-text"> #{tik.message} </div> </div> </div> </h:panelGroup> </ui:repeat>
3. 验证方法参数的有效性
确认tik.from在JSTL执行阶段是否已正确初始化:
- 在
isTicketFromUser方法中添加日志,输出from的ID值,检查参数是否为null或非预期值; - 若
tik.from为null,调用from.getId()会抛出空指针异常,EL会静默处理该异常并返回false,但实际页面可能因为异常导致判断逻辑异常。可在方法中添加非空判断:
public boolean isTicketFromUser(User from) { if (from == null) { return false; // 或根据业务逻辑返回对应值 } return !from.getId().equals(UUID.fromString("hiddenUUID")); }
内容的提问来源于stack exchange,提问作者Farhood Naqizadeh
相关产品推荐
相关产品推荐

