我有 2 个视图 (a.xhtml
和b.xhtml
),其中一个包含指向另一个的链接。第一种观点:
- 通过设置一些值来使用当前视图地图;
- 指向
b.xhtml
withh:link
usingincludeViewParams="true"
以便在链接的查询字符串中自动包含视图参数。
a.xhtml
:
<f:view >
<f:metadata>
<f:viewAction>
<!-- just set any value to force view map creation... -->
<f:setPropertyActionListener target="#{viewScope.username}" value="John" />
</f:viewAction>
</f:metadata>
<h:link id="alink" value="Go to B" outcome="b" includeViewParams="true" />
<h:form>
<h:commandButton id="away" action="b" value="Navigate away" immediate="false" />
</h:form>
</f:view>
</html>
和b.xhtml
:
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:view >
<f:metadata>
<f:viewParam id="id" name="userid" value="1" />
</f:metadata>
</f:view>
</html>
此外,我在这里创建一个ViewMapListener
以演示一旦a.xhtml
被访问就会发生的“虚假”视图地图破坏事件调用。在我的faces-config.xml
我有这个条目:
<system-event-listener>
<system-event-listener-class>org.my.TestViewMapListener</system-event-listener-class>
<system-event-class>javax.faces.event.PreDestroyViewMapEvent</system-event-class>
<source-class>javax.faces.component.UIViewRoot</source-class>
</system-event-listener>
是TestViewMapListener
这样的:
public class TestViewMapListener implements ViewMapListener {
@Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
if (event instanceof PreDestroyViewMapEvent) {
PreDestroyViewMapEvent viewMapEvent = (PreDestroyViewMapEvent)event;
UIViewRoot viewRoot = (UIViewRoot)viewMapEvent.getComponent();
System.out.println("PreDestroyViewMapEvent: "+viewRoot.getViewId());
}
}
...
呈现页面a.xhtml
后,侦听器会打印出以下行:
PreDestroyViewMapEvent: /b.xhtml
这很奇怪,因为b.xhtml
从未访问过。当我使用按钮离开时,"Navigate away"
会按预期打印正确的事件:
PreDestroyViewMapEvent: /a.xhtml
仅当我includeViewParams="true"
在链接上使用时才会触发不正确的事件。通过调试,我可以看到它的发生是因为com.sun.faces.application.view.ViewMetadataImpl.createMetadataView(FacesContext)
临时设置为FacesContext
UIViewRootb.xhtml
创建原始视图地图的浅表副本并将其设置为临时视图根。这样做可能是为了正确检测链接的查询字符串参数值;它还会在操作期间暂时关闭事件,但是它会过早将它们重新打开(参见“finally”块),因此视图地图破坏事件被“错误地”触发为视图地图的临时副本,而没有事件此时预计原始视图地图本身。这是一个令人头疼的问题,因为我需要采取一些额外的措施来检测它是原始地图被破坏还是它的“幽灵”的虚假事件。
这是错误还是期望的行为?我正在使用 Mojarra 2.2.12。